A self-contained app is a great way to share your application as all components, runtime, and framework are included with the application. All you have to provide is the application .exe file without worrying about the presence of framework or runtime installation status on other machines. .NET Core 3.0 Preview 6 is out and there are a lot more new features. One of the useful feature is the introduction of PublishTrimmed
flag. This flag reduces the size of the executable to a great extent and create a trimmed self-contained single executable in .NET Core 3.0.
Create a Trimmed Self-Contained Single Executable in .NET Core 3.0
Today with .NET Core, you can create a self-contained application using the following command.
dotnet publish -r win-x64 -c Release --self-contained
The above command builds the app in release mode and publishes the self-contained app. This will create a folder with the application .exe and other dependencies. So to run this app on another machine, you have to copy the complete folder and run the .exe from there. This is good, but there are more than 100 files and the size is also huge for a simple .NET Core based console application.
This problem is resolved in .NET Core 3.0 Preview 5. This release introduces a flag called PublishSingleFile
which produces a single .exe file. The command can be used in the following way,
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true
OR, you can also specify in the project file.
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <RootNamespace>Hello_.NETCore3</RootNamespace> <PublishSingleFile>true</PublishSingleFile> <RuntimeIdentifier>win-x64</RuntimeIdentifier> </PropertyGroup>
The PublishSingleFile
flag produces the following output. As you can see from the below image, there is only a single .exe file now.
A single .exe now, but the size is still an issue. It is near to 70 MB. This is solved in Preview 6 of .NET Core 3.0 with the introduction of a new flag called PublishTrimmed
which doesn’t include DLL’s that aren’t used to reduced the size. You need to use both the flags together to create a Trimmed Self-Contained Single Executable in .NET Core 3.0. Like,
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
OR, you can also specify both the flags in the project file.
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.0</TargetFramework> <RootNamespace>Hello_.NETCore3</RootNamespace> <PublishSingleFile>true</PublishSingleFile> <PublishTrimmed>true</PublishTrimmed> <RuntimeIdentifier>win-x64</RuntimeIdentifier> </PropertyGroup>
And the result is just a 29 MB single EXE. You should be saying that it is still quite big for a simple console application. But remember, it’s a self-contained application which includes the .NET Core runtime also.
That’s it.
Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.
Great Article loved the detail…
When I publish my .Net Core 3.0 into a single executable, sure enough it created 1 .exe and 1.pdb only. But when I ran the .exe program for the first time, behind the scene it produces a lot of dll files plus the app dll file and config files in a randomly generated folder under C:\Users\\AppData\Local\Temp\.net folder. For example, the folder name was cjewg3k0.ack. And then, when I publish again, and run the .exe for the first time, it would produce another random folder. Is this the way it should be?
Now when I publish with dll option, the .exe is much smaller, but then there is the app .dll, dll.config, json, and reference dlls in the publish folder. The good news is, this one does not create a random folder like the single-executable does.
How to modify application configuration in self contained app.
Great article.
I tried using do this using preview 7, but it doesn’t work as I expect. I’ve tried both using the CLI flag and setting it in the “fsproj” file (it’s a F# project). No matter what I do it publishes everything and I don’t get the single file I expected.
I have this in my fsproj
true
true
Very good.
The important thing to remember about this feature, is that it allows for some flexibility. If this was the ideal solution for every build, it would not be a feature, and would be the default build option. This particular feature is important, as it allows a developer to build with the latest in netcore advancements, and not have to target older frameworks just because a client is unwilling to install the runtimes on a particular server. This is something I have encountered on more than one occassion, and it has kept me developing with older frameworks, which I did not like. As with most things, there are pro’s and con’s, and they would of course have to be discussed with the client. Most clients I know, would objectively favor (and would be quite excited about) not needing to install more runtimes, having only a single self-contained executable to keep track of, and all while minimizing/negating installation procedures due to the inherent portability. These are pain points for the client I’m currently working with, so this is an incredible addition to the framework. I do hope this feature gets optimized/streamlined and it becomes possible to create a self-contained executable that does not include anything beyond only what is used of the framework (to minimize its size as much as possible). This is an incredible start though!
Thank you for the information!
What’s the minimum size of a “Hello World!” self-contained console executable with .NET Core 3 preview 6?
After trimming it comes to 29 mb.
Then that should be the benchmark for future updates since compared to a native C++ (or even a D) app, a trivial program like “Hello World!” gets way higher right now.
yes, it’ a amazing hello world in just 29MB, nothing can touch it, everyone should port there hello worlds to this fabulous Core technology !!
Would this be a good option for running .net core in a docker container?
It depends, imho. Simply using a bare OS image definitely would work but you’d totally miss layer caching.
I translated a Chinese version.
https://www.cnblogs.com/jroger/p/create-trimmed-self-contained-executable-in-net-core-3-0.html
Thanks for the information. Would like to give a try
I alwasy looked at this ‘self-contained’ solution as a desperate workaroud when a developer gets confused of the plethora of incompatible OS, .dll versions, frameworks, etc.
All this just try to evade the real backlog the .NET infrastructure has: the lack for a clear, transparent and unified development and running environment.
I don’t agree with your sentiment. How is this a ‘workaround’? .Net was written to run in a Windows environment. The original framework contains all the required operating system translation. The environment is the IL, and Windows runs the IL natively.
This solution is very close to Java, but java requires you to install the JRE to execute java applications.
They took the “core” of c#, removing all the unnecessary OS bits and created a portable language.
It isn’t about “develipers getting confused” but abstraction and portability. You COULD write everything in c++ but it’s a rather dated language for higher level programming
Will this work with F# too?
Have not tried but should work as it is language agnostic..
I was trying to use it with WPF, but there were errors during build and when I fixed them, I had a problem with running the app.
Thank you very much for the very abstract description of the errors!
If someone gave me a HelloWorld.exe at 28.4MB, I’d wonder what trojan they’d bundled along with it…
I think the idea would be that it doesn’t increase more once you build real world / LOB apps with it, given the cost will mainly be including the framework
After a dozen or so of these (Or hundreds / thousands as would generally be the case), it’d be smaller just to have the .NET Framework installed in the first place…
good one
Is this a good option for a app running in a docker container?
Thanks for information..