C# CodeCompiler errors

Hi,

I am trying to compile dynamically generated C# source code. However, I am having trouble getting the code to work properly due to referenced assemblies not being found. I have tried setting the CompilerOption "/lib:path_to_find_assemblies" but then get a compiler error CS2008 No inputs specified.

I have set the CompilerParameter property GenerateInMemory to true, but the compiler still writes the assembly to disk.

Also it seems as though one can't specify where the generated assembly should be created.

Here is a snippet of my code:

            CSharpCodeProvider provider = new CSharpCodeProvider();
            ICodeCompiler compiler =  provider.CreateCompiler();
           
            //setup compiler options
            CompilerParameters options = new CompilerParameters();
            options.ReferencedAssemblies.Add("System.dll");
            options.ReferencedAssemblies.Add("AnotherAssembly.dll");
            options.OutputAssembly = name+".dll";
            options.GenerateExecutable = false;
            options.IncludeDebugInformation = false;
            options.GenerateInMemory = true;
            options.CompilerOptions = string.Format("/lib:{0}",  baseDir);

            //compile
            CompilerResults results = compiler.CompileAssemblyFromFile(options, path);

where name = the assemblyName to be created, path = the path to the generated source file and baseDir = location to find the referenced assemblies.

Anyone able to assist here

Thanks.

Stefan


Answer this question

C# CodeCompiler errors

  • sspotts

    I have also problem like yours.
    Below is code for compiling code at runtime:

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using Microsoft.CSharp;
    using System.Diagnostics;

    namespace CSWinCompiler
    {
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
    private System.Windows.Forms.TextBox textBox1;
    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.TextBox textBox2;
    private System.Windows.Forms.Button button2;
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;

    public Form1()
    {
    //
    // Required for Windows Form Designer support
    //
    InitializeComponent();

    //
    // TODO: Add any constructor code after InitializeComponent call
    //
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null)
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    }

    #region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
    this.textBox2 = new System.Windows.Forms.TextBox();
    this.textBox1 = new System.Windows.Forms.TextBox();
    this.button1 = new System.Windows.Forms.Button();
    this.button2 = new System.Windows.Forms.Button();
    this.SuspendLayout();
    //
    // textBox2
    //
    this.textBox2.BackColor = System.Drawing.SystemColors.Control;
    this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.None;
    this.textBox2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
    this.textBox2.ForeColor = System.Drawing.SystemColors.WindowText;
    this.textBox2.Location = new System.Drawing.Point(264, 56);
    this.textBox2.Multiline = true;
    this.textBox2.Name = "textBox2";
    this.textBox2.Size = new System.Drawing.Size(240, 232);
    this.textBox2.TabIndex = 2;
    this.textBox2.Text = "";
    //
    // textBox1
    //
    this.textBox1.Location = new System.Drawing.Point(16, 48);
    this.textBox1.Multiline = true;
    this.textBox1.Name = "textBox1";
    this.textBox1.Size = new System.Drawing.Size(240, 240);
    this.textBox1.TabIndex = 0;
    this.textBox1.Text = "textBox1";
    this.textBox1.WordWrap = false;
    //
    // button1
    //
    this.button1.Location = new System.Drawing.Point(352, 296);
    this.button1.Name = "button1";
    this.button1.TabIndex = 1;
    this.button1.Text = "Build";
    this.button1.Click += new System.EventHandler(this.button1_Click);
    //
    // button2
    //
    this.button2.Location = new System.Drawing.Point(432, 296);
    this.button2.Name = "button2";
    this.button2.TabIndex = 1;
    this.button2.Text = "Run";
    this.button2.Click += new System.EventHandler(this.button1_Click);
    //
    // Form1
    //
    this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    this.ClientSize = new System.Drawing.Size(512, 325);
    this.Controls.Add(this.button2);
    this.Controls.Add(this.textBox2);
    this.Controls.Add(this.button1);
    this.Controls.Add(this.textBox1);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);

    }
    #endregion

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
    Application.Run(new Form1());
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
    CSharpCodeProvider codeProvider = new CSharpCodeProvider();
    ICodeCompiler icc = codeProvider.CreateCompiler();
    string Output = "Out.exe";
    Button ButtonObject = (Button) sender;

    textBox2.Text = "";

    System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
    //Make sure we generate an EXE, not a DLL
    parameters.ReferencedAssemblies.Add("System.dll");
    parameters.ReferencedAssemblies.Add("System.Data.dll");
    parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
    parameters.ReferencedAssemblies.Add("System.Collections.dll");
    parameters.ReferencedAssemblies.Add("System.Data.dll");
    parameters.ReferencedAssemblies.Add("System.ComponentModel");
    parameters.ReferencedAssemblies.Add("System.Drawing");

    parameters.GenerateExecutable = false;
    parameters.GenerateInMemory = false;
    parameters.OutputAssembly = Output;
    parameters.CompilerOptions = String.Concat("/lib:", @"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322");
    CompilerResults results = icc.CompileAssemblyFromSource(parameters,textBox1.Text);

    if (results.Errors.Count > 0)
    {
    textBox2.ForeColor = Color.Red;
    foreach(CompilerError CompErr in results.Errors)
    {
    textBox2.Text = textBox2.Text +
    "Line number " + CompErr.Line +
    ", Error Number: " + CompErr.ErrorNumber +
    ", '" + CompErr.ErrorText + ";" +
    Environment.NewLine + Environment.NewLine;
    }
    }
    else
    {
    //Successful Compile
    textBox2.ForeColor = Color.Blue;
    textBox2.Text = "Success!";
    //If we clicked run then launch our EXE
    if (ButtonObject.Text == "Run") Process.Start(Output);

    }

    }
    }
    }



    When I run this application and want to compile below
    code, it displays
    ------
    Line number 0, Error Number: CS0006, 'Metadata file 'System.Collections.dll' could not be found;

    Line number 0, Error Number: CS0006, 'Metadata file 'System.ComponentModel' could not be found;

    Line number 0, Error Number: CS0006, 'Metadata file 'System.Drawing' could not be found;
    -------
    Please, help me.

    Sincerely,
    Teymur



  • pipemx

    Thanks for the reply.

    I have amended my code to not specify the output assembly and no debug information but I still get the same error (fatal error CS2008: No inputs specified). I have checked all my parameters, the directories don't contain spaces, and I have also examined the Output property in the CompilerResults while Debugging, which shows the command-line string that is run as well as the output from the compiler. The command line string appears to be fine and when run manually from the command-line works.

    I have isolated the problem to when the code is run from a console application. As unit test code run from VS.NET (using TestDriven.NET) or from Nunit GUI it works fine! I guess this means it could be an environment issue. I will check my environment variables (PATH etc) and see if I come up with anything. Anything else you can suggest

    I am using Visual Studio .NET 2003, .NET 1.1 and Windows XP SP2.

    Thanks.

    Stefan

    My code is now as follows:

            public static Assembly Compile(string path, string refAssembly)
            {
                //create compiler instance
                CSharpCodeProvider provider = new CSharpCodeProvider();
                ICodeCompiler compiler =  provider.CreateCompiler();
               
                //setup compiler options
                string libDir = AppDomain.CurrentDomain.BaseDirectory;

                CompilerParameters options = new CompilerParameters();
                options.ReferencedAssemblies.Add("System.dll");
                options.ReferencedAssemblies.Add(refAssembly);
                options.GenerateExecutable = false;
                //options.IncludeDebugInformation = false;
                options.GenerateInMemory = true;
                options.CompilerOptions = string.Format("/lib:\"{0}\"", libDir);

                //compile
                CompilerResults results = compiler.CompileAssemblyFromFile(options, path);
                if(results.Errors.HasErrors)
                {
                    //handle errors
                    ......
                    throw new ApplicationException(....);
                } else {
                    //return in-memory assembly
                    return results.CompiledAssembly;
                }
            }

    The output produced is below (as copied directly from Visual Studio .NET debug locals):

        [0]    "C:\\Projects\\DotNet\\SAL\\FormulaTest\\bin\\Debug> \"c:\\windows\\microsoft.net\\framework\\v1.1.4322\\csc.exe\" /t:library /utf8output /R:\"System.dll\" /R:\"SAL.Server.dll\" /out:\"C:\\DOCUME~1\\burwitzs\\LOCALS~1\\Temp\\pe_0sg6n.dll\" /debug- /optimize+ /lib:\"C:\\Projects\\DotNet\\SAL\\FormulaTest\\bin\\Debug\\\"  \"C:\\Projects\\DotNet\\SAL\\FormulaTest\\bin\\Debug\\_Formulas\\Formula_12345.cs\""    string



  • rclakin

    I am not able to duplicate your problem.  If you are getting a compilation error then no output should be generated at all.  Are you sure the output isn't from a previous compilation   The compiler won't automatically delete the previous output before compilation like it does in the IDE.  Nonetheless here is sample code to generate an assembly in memory. 

    Assembly CompileFile ( string strSrcFile )
    {
              string strBaseDir = @"<path to third-party assembly";
    string strAsmName = "<assembly name>";

    CSharpCodeProvider prov = new CSharpCodeProvider();
    ICodeCompiler cmplr = prov.CreateCompiler();

    CompilerParameters parm = new CompilerParameters();
    parm.GenerateExecutable = false;
    parm.ReferencedAssemblies.AddRange(new string[] { "system.dll", strAsmName });                         

    //If this path contains spaces then you must delimit it with quotes
    parm.CompilerOptions = String.Concat("/lib:", strBaseDir);
    parm.GenerateInMemory = true;
    //parm.OutputAssembly = strOutFile;

    CompilerResults res = cmplr.CompileAssemblyFromFile(parm, strSrcFile);
    if (res.Errors.Count > 0)
    {
       foreach (CompilerError err in res.Errors)
       {
          Console.WriteLine(err.ErrorText);
       };
    };

    if (res.Errors.HasErrors)
       Console.WriteLine("Compilation failed.");
    else
       Console.WriteLine("Compilation successful.");       

    return res.CompiledAssembly;
    }

    Michael Taylor - 10/18/05

  • Zano

    Yes I see your problem now.  The issue is that you are using BaseDirectory which, at least on my machine, has a slash at the end.  When the command line compiler parses the string it'll see the slash followed immediately by a quote and assume it is delimited.  This causes the rest of the line, including the source file, to be ignored.  I'd use Environment.CurrentDirectory instead.  And if you really want to be safe then use Trim("\"") on the path before passing it as a parameter.  Once you fix this it'll compile.

    Michael Taylor - 10/18/05

  • ProNovice

    All working now - yes it was the trailing backslash in the lib path that was the offender.

    Thanks again for your help.

  • C# CodeCompiler errors