SAJ14SAJ
SAJ14SAJ

Reputation: 1708

Using Mono.Cecil to generate HelloWorld IL targeting .NET 8, error loading System.Private.CoreLib

I am trying to use Mono.Cecil (v 0.11.5) to emit an IL assembly as an .EXE, written in C# 12 on .NET 8. Almost all of the information I can find on using Mono.Cecil is for .NET Framework.

If it is relevant, the host machine is Windows 11, with the .NET 8 runtime and SDK installed. I am using Rider, and do not have visual Studio installed.

It is emitting the .EXE file (source of emitter below), and the IL within seems correct.

However, when running the .EXE, I get:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The system cannot find the file specified.

How do I make it emit properly for a .NET 8 runtime?


    // Slightly modified from:
    // https://mycodingplace.wordpress.com/2016/11/10/mono-cecil-hello-world/


    public static void Emit()
    {
    // Create a new assembly
    var assembly = AssemblyDefinition.CreateAssembly(
    new AssemblyNameDefinition("HelloWorld", new Version()),
    "HelloWorld",
    ModuleKind.Console);

    // This is the main module you need to work with
    var module = assembly.MainModule;

    // Create a new type called "Program" and add it to main module
    var programType = new TypeDefinition(
        "HelloWorld",
        "Program",
        TypeAttributes.Class | TypeAttributes.Public,
        module.Import(typeof(object)));

    module.Types.Add(programType);

    // create a new method called 'Main' method and add it to 'Program' type
    var mainMethod = new MethodDefinition(
        "Main",
        MethodAttributes.Public | MethodAttributes.Static,
        module.Import(typeof(void)));

    programType.Methods.Add(mainMethod);

    // Get ILProcessor for the method body
    var ilProcessor = mainMethod.Body.GetILProcessor();

    // Load the string "Hello World" to stack
    ilProcessor.Emit(OpCodes.Ldstr, "Hello World");

    // Call Console.WrtieLine(string)
    var writline = module.ImportReference(
        typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }));
    ilProcessor.Emit(OpCodes.Call, writline);

    // Call Console.ReadKey()
    var readKey = module.ImportReference(typeof(Console).GetMethod("Read"));
    ilProcessor.Emit(OpCodes.Call, readKey);

    // You must pop out the return value before you leave the method
    ilProcessor.Emit(OpCodes.Pop);

    // Return
    ilProcessor.Emit(OpCodes.Ret);

    // Because this is an executable assembly, you must define an entry point
    assembly.EntryPoint = mainMethod;

    // Save the assembly to disk
    assembly.Write(@"c:\temp\HelloWorld.exe");
}

Upvotes: 1

Views: 80

Answers (0)

Related Questions