How to make a WinForms app with .NET 5 entirely from the command line and publish as one self-contained file
I got a lovely email from a reader named Steven who has been doing .NET for many years and is excited about .NET 5. He has an interesting perspective:
I really like the .NET library.
During 2020, I've taught myself enough Windows Forms to write my own JPG photo viewer. Sorry but I'm not a fan of XAML, so I just write and compile raw Windows forms in C#.
Now before we start, I would offer that XAML is how you express your UI in WPF, and there is a WinForms designer for .NET Core in the latest version of Visual Studio so if you do want to mix and match using a designer and also writing your WinForms straight you can do that these days.
Steven asks:
I wonder if you could help me with a good recipe for command line compile on C#9 / .NET 5 to make a .exe?
More specifically he adds:
I want to be able to:
- from a command line
- without Visual Studio
- create a standalone .exe file for Windows
- from csharp myprog.cs
- where I don't mind if installing the Windows .NET runtime is a prerequisite
- Using C# 9 and .NET 5
Cool, I can help with that. Using only the .NET 5 SDK which you can install from http://www.dot.net, you can make a single EXE that will run on any Windows Machine in two commands, assuming you are already in a new empty folder.
~\Desktop\forsteven>
dotnet new winforms
The template "Windows Forms App" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on C:\Users\scott\Desktop\forsteven\forsteven.csproj...
Determining projects to restore...
Restored C:\Users\scott\Desktop\forsteven\forsteven.csproj (in 56 ms).
Restore succeeded.
~\Desktop\forsteven>
dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
Microsoft (R) Build Engine version 16.8.0+126527ff1 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.
Determining projects to restore...
Restored C:\Users\scott\Desktop\forsteven\forsteven.csproj (in 94 ms).
forsteven -> C:\Users\scott\Desktop\forsteven\bin\Debug\net5.0-windows\win-x64\forsteven.dll
forsteven -> C:\Users\scott\Desktop\forsteven\bin\Debug\net5.0-windows\win-x64\publish\
First I say dotnet new winforms
which is the command line equivalent for "File | New Project in Visual Studio.
Next I dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
which is a little extra with that last bit, but look at the design for the single file feature you'll see that if you want all the native libraries linked in you have suck in more.
Personally, I think that the last two in the list should just be one. It's not obvious but it turns out it's quite hard as you move into things like WinForms that require some native libraries. Those native libraries don't like being run while embedded in an EXE. To solve this, you can either use IncludeAllContentForselfExtract or IncludeNativeLibrariesForSelfExtract.
Self-Contained Publish
- Normal publish:
dotnet publish -r win-x64
- Published files:
HelloWorld.exe
,HelloWorld.pdb
, and 224 more files- Single-file publish Linux:
dotnet publish -r linux-x64 /p:PublishSingleFile=true
- Published files:
HelloWorld
,HelloWorld.pdb
- Single-file publish Windows:
dotnet publish -r win-x64 /p:PublishSingleFile=true
- Published files:
HelloWorld.exe
,HelloWorld.pdb
,coreclr.dll
,clrjit.dll
,clrcompression.dll
,mscordaccore.dll
- Single-file publish Windows with Extraction:
dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
- Published files:
HelloWorld.exe
,HelloWorld.pdb
So that "WithExtraction" means things get unzipped and run, while the other Single File isn't really single file (because some native bits are outside) but it avoids the temporary directory and just unfolds into memory. So it's more "Single small folder."
The resulting app is one 145 meg EXE that can be run anywhere without installing .NET 5 because we included it all in the EXE.
You can also add /p:PublishTrimmed=true
and it's just 83 megs, again, just one EXE.
Hope this helps!
Sponsor: Need a multi-cluster load balancer and API gateway? Try VoltMesh: built for modern and distributed apps that require automation, performance and visibility. Start for free today.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter