Re: Scripting Engine (somewhat advanced)

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: Joakim Karlsson (jkarlsson_at_NOSPAMjkarlsson.com)
Date: 01/06/05


Date: Thu, 06 Jan 2005 21:22:05 +0100

You can use the Microsoft.JScript.JScriptCodeProvider to accomplish this.

1. Create a string or temporary file or similar containing a class
declaration and the import statements you need.

2. Paste your script method bodies into the class.

3. Use the ICodeCompiler.CompileAssemblyFromSource to generate an in
memory assembly from the source.

4. Call into the methods of the generated type using reflection.

One caveat: you should load the dynamic assembly into an appdomain of
it's own if you intend to load and unload scripts during execution.

/Joakim

A type for handling this make look something like this:

public class JScriptEngine
{
   JScriptCodeProvider codeProvider = new JScriptCodeProvider();

   private object scriptInstance;

   private ArrayList functions = new ArrayList();

   public void AddFunction(string code)
   {
     functions.Add(code);
   }

   public void CompileAssembly()
   {
     // Setup source for script
     string source = GenerateSource();

     CompilerParameters p = new CompilerParameters(
       /*Here you can add references to the host and other assemblies*/);
     p.GenerateExecutable = false;
     p.IncludeDebugInformation = false;
     p.GenerateInMemory = true;
     ICodeCompiler c = codeProvider.CreateCompiler();
     CompilerResults r = c.CompileAssemblyFromSource(p, source);

     if(r.Errors.Count == 0)
     {
       this.scriptInstance =
         r.CompiledAssembly.CreateInstance("Script");
     }
     else
     {
        // TODO: Handle compiler errors properly.
     }
   }

   private string GenerateSource()
   {
     StringBuilder sb = new StringBuilder();
     sb.Append(
       "import System;\n" +
       "import Whatever you need;\n" +
       "class Script {\n");

       // Add the functions
       foreach(string code in functions)
       {
         sb.Append(code);
       }

       sb.Append("}\n");

       return sb.ToString();
   }

   public void CallFunction(string name, object[] args)
   {
     Type type = scriptInstance.GetType();
     type.InvokeMember (name,
       BindingFlags.InvokeMethod |
       BindingFlags.Default,
       null, scriptInstance, args );
   }
}

John Puopolo wrote:
> All:
>
> I am writing an application (.NET 1.1/C#/VS.NET 2003) that would benefit
> from having a scripting language as part of the program - much like VBScript
> can be used in Excel to automate it.
>
> I would like to use Javascript as the scripting language.
>
> Any idea how I would go about solving this problem? My assumption is that I
> would need to host the scrpting engine and provide calls into and out of the
> engine via some interfaces (COM?). If this is the basic path, I am
> wondering if there is a ".NET" way to do this, or do I need to fall back on
> COM and COM interfaces?
>
> In addition, what if I were to switch from wanting to use Javascript to
> wanting to use C#? I could certainly use the compiler services, etc. to
> load and build an assembly, but how would I expose the host's applicaton
> objects to the script and vice versa?
>
> Many thanks,
> John
>
>
>
>



Relevant Pages

  • Re: How to rewrite with awk?
    ... > I'm unfamiliar with tools such as sed & awk. ... Extract the string that matches a RE. ... This script will not only expand all the lines that say "include ... file) and not resetting ARGV(the tmp file), it then lets awk do any ...
    (comp.unix.shell)
  • Re: Slow string
    ... I see virtually no difference in execution time for the code you posted when using cscript versus using wscript; to confirm, I bracketed the code with an initial ... Are you actually entering the script name into a console window? ... You can use the exact same line for every wrapper script - and that includes wsf and js scripts; all you need to do is change the final "vbs" to "wsf" or "js" as appropriate. ... If you build a large string by small concatenations, the performance degrades geometrically - so does array resizing, because they both use the same nasty technique inherited from VB1 of copying the entire data structure to a new structure with the added element. ...
    (microsoft.public.scripting.vbscript)
  • Re: Function that returns date of file.
    ... string after the date/time when it is used by itself. ... Is that your entire script? ... I make an IF statement that required the 'equals equals'. ... designed database your job will be all that much harder. ...
    (alt.php)
  • Re: Script: Remote shutdown of all domain computers
    ... When trying to run the script from a XP workstation, where i am logged in as ... Dim strBase, strFilter, strAttributes, strQuery, objRecordSet ... 2000 or above and allow shutdown, ... Public Function AllComputersAs String() ...
    (microsoft.public.windows.server.scripting)
  • Re: Update Notes Field
    ... I was able to run the script without any problems. ... The info attribute can be assigned a value when the user object is created, but I don't see where dsadd can do it. ... Most attributes are string values, and VBScript strings can include the character vbCrLf. ... If there is another way to add the information to the Notes field, ...
    (microsoft.public.windows.server.active_directory)