Reputation: 2314
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
Upvotes: 6
Views: 12500
Reputation: 2314
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
Upvotes: 5
Reputation: 272905
The entry point must be named Main
, as specified by the C# language specification §3.1:
3.1 Application Startup
Application startup occurs when the execution environment calls a designated method, which is referred to as the application's entry point. This entry point method is always named
Main
, and can have one of the following signatures:static void Main() {...} static void Main(string[] args) {...} static int Main() {...} static int Main(string[] args) {...}
See the words "is always named Main
"? If you changed your entry point to something other than Main
by writing another compiler, that compiler wouldn't be a C# compiler by definition. :)
Upvotes: 2
Reputation: 13674
This is not possible, by definition Main
is the entry point of a C# application.
The Main method is the entry point of a C# application. (Libraries and services do not require a Main method as an entry point.) When the application is started, the Main method is the first method that is invoked.
Source: MSDN
Upvotes: 2
Reputation: 109100
The method does have to be called Main
, but you can use the -main
option to designate which class's Main
method is the entry point.
(The use of Main
as the entry point is part of the definition of C# – in the C# v5 specification it is in §3.1, you might be able to overcome this but you would be on your own.)
Upvotes: 2