首页 > 解决方案 > 如何更改 ac# 控制台应用程序的入口点?

问题描述

我想知道是否可以将 .NET 控制台应用程序入口点从以下示例中的方法Main更改为:Main2

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

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

我调查了这两个的 IL 代码。这是Main方法:

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

    // other instructions

  } // end of method Program::Main

Main2方法:

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

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

唯一的区别是该方法中.entrypoint指令的存在Main,据我所知,CLR 在启动应用程序时检测到该指令。

有没有办法影响csc用这个指令标记其他方法?其他编译器可以做到这一点吗?

编辑 我的问题与这个不同,因为我在询问csc 编译器(和其他编译器)的行为......特别是如何将.entrypoint指令放在另一个地方

标签: c#.netclrcilcsc

解决方案


这可以通过使用库中AssemblyBuilder的其他内容来实现System.Reflection

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");

这将产生以下IL代码(.entryPoint放置在Main2方法上):

.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

如果你执行Test.exe,你会看到Main2方法被执行


推荐阅读