How can I run code from a string?

449 views Asked by At

I have a textbox in my program. In the textbox you can write the name of function/method you want to run as well as pass parameters. This is all parsed and via a big switch block if my case is filled I the code for that specific case, as well as passing the parameters.

But what I really want to do is to use stringbuilder to build source code and then run it!

This is an example of source code built with my stringbuilder.

 outlook outlooken = new outlook(appNwindow);

and

  outlooken.createNewEmail(scriptarray[i][1],scriptarray[i][2],
  scriptarray[i][3],scriptarray[i][4]);

Using stringbuilder to create strings is no problem at all. But how do I run them?

I have tested a lot, and managed to get everything in place but I think I'm missing something cuase my code always generates an error...

Here's my soruce code

 CodeDomProvider myCodeDomeProvider = CodeDomProvider.CreateProvider("CSharp");
 String [] referenceAssemblies = {"System.dll"};
 //  string myAssemblyName = "myAssembly.dll";
 CompilerParameters myCompilerparameters = 
 new CompilerParameters(referenceAssemblies);

        myCompilerparameters.GenerateExecutable = false;
        myCompilerparameters.GenerateInMemory = true;

  //*** Here's the sourcecode it want to compile
  string[] arr1 = new string[] { "outlook outlooken = new outlook(appNwindow);","outlooken.createNewEmail(scriptarray[i][1],scriptarray[i][2],scriptarray[i[3],scriptarray[i][4]);"};

        CompilerResults myResults = myCodeDomeProvider.CompileAssemblyFromSource(myCompilerparameters, arr1);
        string objectname = "testet";
        string method = "createNewEmail";
        object[] args = new object[2];

        args[0] = "to";
        args[1] = "CC";

        if (myResults.Errors.HasErrors)

         {
            StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
            foreach (CompilerError error in myResults.Errors)
            {
            errors.AppendFormat("Line {0},{1}\t: {2}\n",
            error.Line, error.Column, error.ErrorText);
            }

            throw new Exception(errors.ToString());
            }
            else
            {
            Assembly assem = myResults.CompiledAssembly;
            object instance = null;

            Type type = assem.GetType(objectname);
            MethodInfo miChk = type.GetMethod(method);

            if (!miChk.IsStatic)
            {
            instance = assem.CreateInstance(objectname);
            type = instance.GetType();
            }

            MethodInfo mi = type.GetMethod(method);

            mi.Invoke(instance, args);
            }

These are the errors I get when running it:

Additional information: Compiler Errors :

Line 1,1 : A namespace cannot directly contain members such as fields or methods

Line 1,25 : Expected class, delegate, enum, interface, or struct

Line 1,1 : A namespace cannot directly contain members such as fields or methods

Line 1,41 : Identifier expected

Line 1,59 : Identifier expected

Line 1,77 : Identifier expected

Line 1,95 : Identifier expected

1

There are 1 answers

0
Reed Copsey On BEST ANSWER

CodeDom won't compile and execute an arbitrary statement. The code you compile must be valid C# code, just as if you were doing a C# file from source.

This means you need to wrap the statement into a namespace + class, and put it within a method (could be static) in the class.

Basically, think of the input as if you were writing a normal C# file and compiling the .cs file with the compiler - you'll need the same "text" in your input.