如何更改c#控制台应用程序';什么是切入点?
我想知道在下面的示例中,是否可以将.NET控制台应用程序入口点从如何更改c#控制台应用程序';什么是切入点?,c#,.net,clr,cil,csc,C#,.net,Clr,Cil,Csc,我想知道在下面的示例中,是否可以将.NET控制台应用程序入口点从Main更改为Main2方法: class Program { static void Main(string[] args) { Console.WriteLine("Main"); } //desired entry point static void Main2(string[] args) { Console.WriteLine("Main2
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
.method private hidebysig static void
Main2(
string[] args
) cil managed
{
.maxstack 8
//other instructions
} // end of method Program::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
以及Main2
方法:
.method private hidebysig static void
Main(
string[] args
) cil managed
{
.entrypoint
.maxstack 8
// other instructions
} // end of method Program::Main
.method private hidebysig static void
Main2(
string[] args
) cil managed
{
.maxstack 8
//other instructions
} // end of method Program::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
唯一的区别是Main
方法中.entrypoint
指令的进位,据我所知,该指令在应用程序启动时由CLR检测
是否有任何方法影响csc使用本指令标记其他方法?其他编译器可以做到这一点吗
编辑
我的问题不同于,因为我问的是
csc
编译器(和其他编译器)的行为。。。具体来说,如何将.entrypoint
指令放在另一个位置该方法必须被称为Main
,但您可以使用该选项指定哪个类的Main
方法是入口点
(使用
Main
作为入口点是C#定义的一部分–在C#v5规范中,它在§3.1中,您可能能够克服这一点,但您需要自己解决。)这是不可能的,根据定义Main
是C#应用程序的入口点
主要方法是C#应用程序的入口点。(库和服务不需要主方法作为入口点。)
应用程序启动时,主方法是第一个方法,即
调用
来源:根据C语言规范§3.1的规定,入口点必须命名为Main
:
3.1应用程序启动
应用程序启动在执行环境调用指定的方法时发生,该方法称为应用程序的条目
指向此入口点方法始终命名为Main
,并且可以具有
下列签名之一:
static void Main() {...}
static void Main(string[] args) {...}
static int Main() {...}
static int Main(string[] args) {...}
请参见“始终命名为
Main
”?如果您通过编写另一个编译器将入口点更改为除Main
之外的其他内容,则该编译器根据定义不会是C#编译器 这可以通过使用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
方法上):
如果执行
Test.exe
,您将看到执行了Main2
方法@Caramiriel yes,即使使用visual studio也可以执行此操作。我的问题更多的是关于将一个具有不同签名的方法标记为入口点的可能性。您能提供更多的上下文吗?您是否正在尝试在不必对生成的代码进行后处理的情况下执行此操作?使用Main2
而不是Main
的目的是什么?目前,这感觉像是一个XY问题。好吧,我认为您应该能够,但不能使用csc编译器。Ilasm.exe是您需要的,但我怀疑它是否比仅添加一个带有main方法的新类更实用。您回复的Caramiriel评论的可能副本似乎已被删除,因此如果我问相同的问题,我深表歉意,但是:您是出于好奇还是有实际原因?因为在语言中还有其他方法可以实现这一点-取决于您试图做什么,您可以从Main调用Main2,或者使用预处理器符号(条件编译),或者使用Richard回答中提到的-Main选项,甚至可以在运行时根据参数从Main调用不同的方法来执行此操作。另外,static async Task Main(string[]args)
;)@将军我想知道为什么这个签名不在规格上。。。我在这里引用的规范是5.0版本async
在当时肯定存在。我认为是C#7.x支持它,我不认为官方的规范可以用于它,是的,但是你特别问过如何使用csc.exe
。在此代码示例中,您使用的是AssemblyBuilder
。