Search code examples
.netcilreflection.emit

How to add the .entrypoint directive to a method (dynamic assembly)


I want to create a simple application using the classes in System.Reflection.Emit. How can I add the enrypoint directive to the Main method?

AssemblyName aName = new AssemblyName("Hello");
AssemblyBuilder aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);

ModuleBuilder mBuilder = aBuilder.DefineDynamicModule("Module");

TypeBuilder tb = mBuilder.DefineType("Program", TypeAttributes.Public);

MethodBuilder methodBuilder = tb.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static);

ILGenerator ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.EmitWriteLine("Hello!");

aBuilder.SetEntryPoint(methodBuilder);
tb.CreateType();
aBuilder.Save("Hello.exe");

AssemblyBuilder.SetEntryPoint does not seem to achieve this.


Solution

  • Try this (I've put comments on modified lines):

    AssemblyName aName = new AssemblyName("Hello");
    AssemblyBuilder aBuilder = AppDomain
        .CurrentDomain
        .DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);
    // When you define a dynamic module and want to save the assembly 
    // to the disc you need to specify a filename
    ModuleBuilder mBuilder = aBuilder
        .DefineDynamicModule("Module", "Hello.exe", false);
    TypeBuilder tb = mBuilder
        .DefineType("Program", TypeAttributes.Public);
    MethodBuilder methodBuilder = tb
        .DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static);
    
    ILGenerator ilGenerator = methodBuilder.GetILGenerator();
    ilGenerator.EmitWriteLine("Hello!");
    
    // You need to always emit the return operation from a method 
    // otherwise you will get an invalid IL
    ilGenerator.Emit(OpCodes.Ret);
    
    aBuilder.SetEntryPoint(methodBuilder);
    tb.CreateType();
    aBuilder.Save("Hello.exe");