Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change a c# console application's entry point?

Tags:

c#

.net

clr

cil

csc

I am wondering whether it is possible to change a .NET console application entry point from Main to Main2 method in the example below:

class Program
{ 
    static void Main(string[] args)
    {
        Console.WriteLine("Main");
    }

    //desired entry point
    static void Main2(string[] args)
    {
        Console.WriteLine("Main2");
    }
}

I investigated an IL code of those two. Here is Main method:

  .method private hidebysig static void 
    Main(
      string[] args
    ) cil managed 
  {
    .entrypoint
    .maxstack 8

    // other instructions

  } // end of method Program::Main

And the Main2 method:

.method private hidebysig static void 
    Main2(
      string[] args
    ) cil managed 
  {
    .maxstack 8

    //other instructions
  } // end of method Program::Main2

The only difference is precense of the .entrypoint instruction in the Main method, which is - as far as I understand - detected by CLR when application is started.

Is there any way to influence csc to mark other method with this instruction? Can other compilers do the trick?

EDIT My question is different from this one, because I am asking about csc compiler (and other complilers) behavior... specifically how to put the .entrypoint instruction in the other place

like image 927
Artem Avatar asked Mar 06 '23 06:03

Artem


1 Answers

This can be achieved by using AssemblyBuilder and other stuff from the System.Reflection library.

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"),AssemblyBuilderAccess.Save);
TypeBuilder typeBuilder = assemblyBuilder.DefineDynamicModule("Module","Test.exe",false).DefineType("Program",TypeAttributes.Public);
MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main2",MethodAttributes.Public|MethodAttributes.Static);
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.EmitWriteLine("Main2");
ilGenerator.Emit(OpCodes.Ret);
assemblyBuilder.SetEntryPoint(methodBuilder);
typeBuilder.CreateType();
assemblyBuilder.Save("Test.exe");

This produces the following IL code (.entryPoint is placed on Main2 method):

.method public static 
void Main2 () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 11 (0xb)
    .maxstack 1
    .entrypoint

    IL_0000: ldstr "Main2"
    IL_0005: call void [mscorlib]System.Console::WriteLine(string)
    IL_000a: ret
} // end of method Program::Main2

If you execute Test.exe you'll see that the Main2 method is executed

like image 169
Artem Avatar answered Mar 16 '23 07:03

Artem