Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Self-Contained Executable With .NET Core 3.0 on Windows, Linux, and Raspberry Pi

DZone 's Guide to

Self-Contained Executable With .NET Core 3.0 on Windows, Linux, and Raspberry Pi

Create self-contained and and minimally trimmed executables with .NET Core 3.0.

· Web Dev Zone ·
Free Resource

.NET Core 3.0 comes with support for self-contained executables. It means we can publish applications as a single executable for a specified platform. Trimming — removing of unused code from assemblies — is also supported. This blog post demonstrates how to build a self-contained executable using .NET Core 3.0.

As of writing this post the current version of .NET Core 3.0 is Preview 7. Not everything is stable yet, and over coming versions, we will probably see many improvements to self-contained executables.

What Is a Self-Contained Executable?

Before any coding, I will introduce some important terms.

  • Self-contained executable — executable file containing program and all needed assemblies (one exe-file we can run). Making of self-contained-executable
    Making of self-contained-executable
  • Trimmed executable — self-contained executable where dependent assemblies have all not used code removed. (If StringBuilder is not used, StringBuilder is removed from an executable). Trimmed executables can be much smaller than original ones due to removed code.
    Trimming of self-contained executable

The trimmed executable is risky business. Programs may use reflection. Types loaded through reflection may easily fly under the radar and be victims of trimming. It is possible to specify what types cannot be trimmed. I don’t stop on this topic right now. 

Getting Started

Let’s start with golden classics of our industry – the almighty “Hello, world” written in C#.

class Program {    
  static void Main(string[] args)    {        
    Console.WriteLine("Hello World!");    
  }
}


We can publish it like we have done this far by typing:

dotnet public -c Release -r win10-x64


What we get is a publish folder with a load of files needed by our application:

  • 255 files.
  • 65.8 MB.

In Windows Explorer, we can see many files in the publishing folder.

Assemblies of .NET Core application

Assemblies of .NET Core


Most of these files are actually very small, so it makes sense to link all assemblies together into one file.

Publishing a Self-Contained Executable

Let’s publish an application now as self-contained executable by typing:

dotnet publish -c Release -r win10-x64 /p:PublishSingleFile=true


Things just got better:

  • 2 files.
  • 65.8 MB.

We now have one executable and its program debug database (pdb-file).

Trimming Self-Contained Executable

We are not done yet. We have platform-specific assemblies in one file with our application, but there’s tons of code our application doesn’t use.

Let’s trim out unused code. To get a trimmed self-contained executable we have to type:

dotnet publish -c Release -r win10-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true


Now things are nice in our publish folder:

  • 2 files.
  • 25.3 MB.

But we have a warning in publishing output:

Optimizing assemblies for size, which may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink


This time we were lucky — our program is so primitive that there’s no chance for something to go wrong.

Self-Contained Web Application

Let’s try what happens with the default ASP.NET Core MVC application when published as a self-contained executable. Just create a default web application and publish it.

dotnet public -c Release -r win10-x64


This is what we will get:

  • 87.3 MB.
  • 393 files, 13 folders.

Let’s make a self-contained executable now by typing:

dotnet publish -c Release -r win10-x64 /p:PublishSingleFile=true


The result is odd:

  • 87.4 MB.
  • 3 files, 0 folders.

Where is wwwroot? Let’s run the application to see what happened.

Self-contained web application with no styles


The content root is missing. Let’s copy the wwwroot folder to the publish folder and try again (also settings file were not published but we don’t need these for this example anyway).

Self-contained web application is ready for deployment


The result is the same although we have content folder available. We have to stop the web application and run it again to make it understand that wwwroot folder is there.

Self-contained web application with styles


One thing to notice — the web application starts extremely fast.

Trimmed Self-Contained Web Application

Let’s see what happens to the web application if we publish it as a trimmed self-contained executable. The publish command is the same as above:

dotnet publish -c Release -r win10-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true


What we got is:

  • 52.5 MB.
  • 3 files, 0 folders.

Okay, we need to copy wwwroot to publish the folder again.

The web application is a different beast, and it comes with many assemblies. It’s interesting to find out if the trimmed executable works or not. It comes up fast, and there are no errors.

Let’s make the first request, as our application just started. And the troubles start… This is how our first request ends.

An unhandled exception has occurred while executing the request.
System.IO.FileNotFoundException: Could not load file or assembly 'System.Threading.Tasks, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'System.Threading.Tasks, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'


From ILLink.Tasks documentation we can read:

“Applications or frameworks (including ASP.NET Core and WPF) that use reflection or related dynamic features will often break when trimmed, because the linker does not know about this dynamic behavior, and can not determine in general which framework types will be required for reflection at runtime. To trim such apps, you will need to tell the linker about any types needed by reflection in your code, and in packages or frameworks that you depend on. Be sure to test your apps after trimming.”

At this point I ran out of ideas, as adding reference to System.Threading.Tasks didn’t work. Also, the suggestion to use something like typeof(Task) somewhere in code didn’t worked out. I think trimming the web application is a more complex topic, and it’s worth it to come back to it when .NET Core 3.0 is released.

Running a Self-Contained Web Application on Windows 10 IoT Core

I hoped to get trimmed executable work because it’s only good when web application running on board is as minimal as possible. But self-contained executable is also okay.

Before publishing, we need to change the Program.cs file of web application and make the web application listen to all interfaces in port 5000.

public static IHostBuilder CreateHostBuilder(string[] args) =>    
  Host.CreateDefaultBuilder(args)        
  	.ConfigureWebHostDefaults(webBuilder =>        
    {            
      webBuilder.UseStartup<Startup>();            
      webBuilder.UseUrls("http://*:5000/");        
    });


Make sure this port is open on board. (More information is available in my blog post Installing ASP.NET Core 3.0 on RaspberryPi and Windows 10 IoT Core.)

Let’s publish our web application now for Windows 10 Iot Core:

dotnet publish -c Release -r win10-arm /p:PublishSingleFile=true


After publishing, we have to copy wwwroot from the project folder to the publish folder. The easiest way to copy the web application to Windows 10 IoT Core is using Windows Explorer.

After this, we have to log in to Windows 10 IoT Core using PowerShell and run web application from there.

Self-contained web application with styles


On my old RaspberryPi 2, the web application is not very demanding:

  • CPU: up to 5%.
  • Working set: 43.2MB.

And best of all things — it works smoothly.

Using Project File

We don’t have to use command line arguments to link and trim executables. It’s possible to add these settings to the project file instead.

<Project Sdk="Microsoft.NET.Sdk">   
	
  <PropertyGroup>    
    	<OutputType>Exe</OutputType>     
     	<TargetFramework>netcoreapp3.0</TargetFramework>    
     	<!-- comment out for web application -->    
     	<PublishTrimmed>true</PublishTrimmed>    
     	<PublishReadyToRun>true</PublishReadyToRun>    
     	<PublishSingleFile>true</PublishSingleFile>    
     	<RuntimeIdentifier>win-x64</RuntimeIdentifier>  
    </PropertyGroup> 

</Project>


You can find out more about it from an excellent blog post Making a tiny .NET Core 3.0 entirely self-contained single executable by Scott Hanselman.

Running Self-Contained Executables on Linux

Self-contained executables can be run also on Linux. As Jeremy Morgan points out in his blog post, Creating Trimmed Self Contained Executables in .NET Core, then self-contained executables published for Linux don't require installation of .NET Core on Linux, but prerequisites for .NET Core on Linux are required.

NB! Publishing ready-to-run executables on Windows 10 for Linux is currently not supported but you can use Windows Subsystem for Linux (WSL). To get WSL running on Windows 10 head over to my blog post Running ASP.NET Core applications on Windows Subsystem for Linux but skip the part of installing .NET Core.

First, install .NET Core 3.0 on Linux that you are running with WSL.

You can access your computer disks by going to /mnt folder and moving further to the disk you like. I built a “Hello, World” console application with the following command.

sudo dotnet publish -r linux-x64 -c Release


It is published to the same location, as in Windows and best of all — it worked too.

Wrapping Up

Self-contained and trimmed executables are interesting features of coming .NET Core 3.0. For some programs, it makes sense to have just one executable containing everything needed to run it. I see trimming as the most important feature. Minimally trimmed executables are a perfect fit for applications running on IoT boards. I hope that the stable release of .NET Core 3.0 supports ASP.NET Core with trimming.

Topics:
web dev ,.net core ,asp ,self-contained ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}