Поделиться через


Compiling code at runtime, C# 3.0 and "Compiler executable file csc.exe cannot be found"

Compiling code at runtime is incredibly easy thanks to the CSharpCodeProvider class. But as always, there is a catch. Let's say you have the following code snippet somewhere in your shiny new VC# 2008 project:

CSharpCodeProvider codeProvider = new CSharpCodeProvider();

CompilerResults results = codeProvider.CompileAssemblyFromSource(new CompilerParameters(), @"

    public class Foo

    {

        public int MyProperty { get; set; }

    }

    public static class Bar

    {

        private static Foo myFooValue = new Foo { MyProperty = 42 };

        public static Foo MyFoo { get { return myFooValue; } }

    }");

foreach (String msg in results.Output)

    Debug.WriteLine(msg);

PropertyInfo myPropertyPi = results.CompiledAssembly.GetType("Foo").GetProperty("MyProperty");

PropertyInfo myFooPi = results.CompiledAssembly.GetType("Bar").GetProperty("MyFoo");

Object PropertyValue = myPropertyPi.GetValue(myFooPi.GetValue(null, null), null);

Debug.WriteLine("Value of Bar.MyFoo.MyProperty: " + PropertyValue.ToString());

Now, the code passed to CompileAssemblyFromSource() doesn't do anything useful but it uses auto-implemented properties and object initializers which are both C# 3.0 features. While this code seems to look good it will crash with a FileNotFoundException with the message "Could not load file or assembly 'file:///C:\Users\[username]\AppData\Local\Temp\[tempfilename].dll' or one of its dependencies. The system cannot find the file specified. " as soon as it tries to read the CompiledAssembly property. Assuming you built a debug version the debug output will reveal why:

Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.1434

for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727

Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

c:\Users\[username]\AppData\Local\Temp\[tempfilename].0.cs(9,61): error CS1526: A new expression requires () or [] after type

The first line is the interesting one. Despite the fact that a new project in VC# 2008 targets the .NET Framework 3.5 by default the CSharpCodeProvider is invoking version 8.0 of the C# compiler which first shipped with the .NET Framework 2.0 and of course doesn’t know anything about the latest C# language features. Now, there are several websites suggesting using a different CSharpCodeProvider constructor with the following input:

CSharpCodeProvider codeProvider = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "3.5" } });

 

The only problem is that it will not work. We've trade the FileNotFoundException for an InvalidOperationException with the dreaded message "Compiler executable file csc.exe cannot be found. " which will be thrown by CompileAssemblyFromSource(). Fortunately, there is literally only one little character between us and success:

 

CSharpCodeProvider codeProvider = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v3.5" } });

 


This posting is provided "AS IS" with no warranties, and confers no rights.