Introduction
As all books or materials showed that a .NET/C# application starts with a Main
method. But we can write multiple Main
methods in our project, then we can choose the correct one you wanted.
You may think that multiple Main
is useless, but when your project has different startup processes depend on different compile conditions or you have to change a lot of codes to start your application, it may be a good choice to write multiple Main
methods.
Details
The original link is .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换 - walterlv. But this blog was written in Chinese, so I translate its content to English. Waterlv is an MVP(Microsoft Most Valuable Professional), and he is good at .NET Core\WPF\.NET. Here is his Blog.
Where can we choose the correct Main
method.
At the project which has Main
method, the steps are listed below :
Right click (show menu items)->Properties->Application->Startup object . As we can see,the default value of startup object is Not set.
Choose the correct Main
method.
If there are multiple Main
methods, and we don’t select a value at Startup object (the value is “Not set”), we will get an error when we compile these codes.
Here is the message of the compile error.
Error CS0017
The program has more than one entry point defined. Compile with /main to specify the type that contains the entry point.
Walterlv.Demo.Main C:\Users\lvyi\Desktop\Walterlv.Demo.Main\Walterlv.Demo.Main\NewProgram.cs
We can fix this error by choosing the correct Main
method.
We write a WPF application
At this step, we can do some more complicated works that we changed the application to the WPF application.
Change the startup object to Walterlv.Demo.App
.
Then, we start this WPF application.
It is important to note that, if you use new .csproj file in your project, the contents are as follows1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<LanguageTargets>$(MSBuildToolsPath)\Microsoft.CSharp.targets</LanguageTargets>
<RootNamespace>Walterlv.Demo</RootNamespace>
<StartupObject>Walterlv.Demo.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml" SubType="Designer" Generator="MSBuild:Compile" />
<Page Include="**\*.xaml" Exclude="App.xaml" SubType="Designer" Generator="MSBuild:Compile" />
<Compile Update="**\*.xaml.cs" DependentUpon="%(Filename)" />
</ItemGroup>
</Project>
We keep the default code in App.xaml file.1
2
3
4<Application x:Class="Walterlv.Demo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Application>
And the codes in App.xaml.cs file are pretty simple.1
2
3
4
5
6
7
8
9
10
11
12
13
14using System.Windows;
namespace Walterlv.Demo
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
var window = new MainWindow();
window.Show();
base.OnStartup(e);
}
}
}
When we run the application now, the Main
methods in Program
file and NewProgram
file do not work, because we set Walterlv.Demo.App
as the value of Startup Object.
Switch different startup processes depending on the Startup Object
Now, you got a functional requirement
The startup processes changes depending on the value of Startup Object.
Specifically, if we start the Main
method in Program
file we startup an APP, also if we start Main
in NewProgram
we run another APP.
So, we can create a new file APP.new.xaml.cs
which share the same xaml file (APP.xaml
) with App.xaml.cs
.
And we have to change the code in .csproj, the codes are as follow
1 | <Project Sdk="Microsoft.NET.Sdk"> |
We can se that it add some judgement code in this .csproj
, it can run deffirent .xaml.cs
files depend on the value of $(StartupObject)
.
Base on the above, we have different .xaml.cs
file for different values of Startup Object. We can write different codes in these two files.
For example,the code in App.new.xaml.cs
are as followed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18using System.Windows;
namespace Walterlv.Demo
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
var window = new MainWindow
{
Title = "New Walterlv Demo",
};
window.Show();
base.OnStartup(e);
}
}
}
They are different with the codes in App.xaml.cs
,we change the title of window in these code.
Replace files with conditional compilers
If there are just a little differences among your startup processes in your project, you can use the conditional compiler to replace files.1
2
3
4
5
6<PropertyGroup Condition=" '$(StartupObject)' == 'Walterlv.Demo.Program' ">
<DefineConstants>$(DefineConstants);OLD</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(StartupObject)' == 'Walterlv.Demo.NewProgram' ">
<DefineConstants>$(DefineConstants);NEW</DefineConstants>
</PropertyGroup>
Currently,you can use coditional compilers to control your startup processes.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20using System.Windows;
namespace Walterlv.Demo
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
var window = new MainWindow()
+ #if NEW
{
Title = "New Walterlv Demo",
};
+ #endif
window.Show();
base.OnStartup(e);
}
}
}