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.