My goal is to create a console application using Roslyn programmatically:
string codeToCompile = @"
using System;
public class Program
{
public static void Main()
{
Console.WriteLine(""Hello World!"");
Console.ReadLine();
}
}";
// Parsing the code into the SyntaxTree
var syntaxTree = CSharpSyntaxTree.ParseText(codeToCompile);
var dotNetCoreDir = Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location);
var refPaths = new[] {
typeof(Object).GetTypeInfo().Assembly.Location,
typeof(Console).GetTypeInfo().Assembly.Location,
Path.Combine(dotNetCoreDir, "System.Runtime.dll")
};
var references = refPaths.Select(r => MetadataReference.CreateFromFile(r)).ToArray();
// Compiling
var compilation = CSharpCompilation.Create(Path.GetRandomFileName())
.WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
.AddReferences(references)
.AddSyntaxTrees(syntaxTree);
compilation.Emit("output.exe", "output.pdb");
However the generated output.exe
doesn't work as Windows executable:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=<7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.
But it does seem to work using the Dotnet tool:
dotnet output.exe // Hello World!
My understanding: .NET Core assemblies cannot be invoked directly, which is why I wasn't able to execute the assembly in the first case. Instead, I must use a CoreCLR host.
My question: would it be possible to modify my approach to create an executable that can be run directly?