Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Publish .NET Core App As Portable Executable

I have a simple .net core app and publish it by following command:

 dotnet publish -c Release -r win10-x64

SqlLocalDbStarter.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" />
  </ItemGroup>

</Project>

When publish process finished dotnet create win10-x64 folder at bin\Release folder then after open it the folder contains publish folder and some dll and exe files.

There are some issue for me:

  • Which one of exe files (inside / outside publish folder) i need to PE app?
  • Why when i cut exe file and move it in other place it doesn't run (without message)?
  • If I need all of dll files to run application, so there are tow options for me (inside / outside publish folder), inside publish folder size is 66 MB but outside publish folder is 1 MB.
  • I want to have a one exe file to run my program without dll files.

Folder Size Image

like image 938
Soheil Alizadeh Avatar asked Jun 05 '18 15:06

Soheil Alizadeh


People also ask

How do you distribute a .NET application?

The . NET Framework provides the following options for distributing applications: Use XCOPY or FTP. Because common language runtime applications are self-describing and require no registry entries, you can use XCOPY or FTP to simply copy the application to an appropriate directory.

How do I publish a .NET Core 3.1 application?

Published your ASP.NET Core Web API as FDD So open Visual Studio and Go to File -> New -> Project. Select ASP.NET Core Web Application and click on Next. Give the proper name to your project and click on Create.


3 Answers

.NET Core 3.0

.NET Core 3.0 supports it out of the box. It packs all stuff in one .exe file (~68 MB for a basic console app). There is PublishTrimmed=true option that can decrease size to ~28 MB by analyzing static code references and excluding unused framework assemblies from the final build.

To configure single exe build edit your csproj file:

<PropertyGroup>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

or on the command line in a folder with csproj file:

dotnet publish -r win-x64 -p:PublishSingleFile=true

For more details see a great answer given by Gopi.

Standalone utils

Warp (thanks to Darien Shannon for mentioning it in the comment) and dotnet CoreRT. Both work with previous versions of .Net Core also

Warp

It is a tool similar to ILMerge for the classic .NET Framework. It is very easy to use. For the basic console app, It can produce .exe ~35 MB without tree shaker and around 10-15 MB with tree shaker.

Dotnet CoreRT

As of Jan 2022 this project is superseded by NativeAOT experiment in dotnet/runtimelab repo. Thanks to @t.j.

For now, you can try to pre-compile the application into a native single-file executable using dotnet CoreRT project. I'm saying "try" because documentation says:

This project is in the early stages of its development.

Nevertheless, it works at least for simple applications. See the sample here. According to its description, you need to run the following command in the project folder:

dotnet new nuget 

This will add a nuget.config file to your application. Open the file and in the element under add the following:

<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />

Then run this:

dotnet add package Microsoft.DotNet.ILCompiler -v 1.0.0-alpha-* 

Then run this:

dotnet publish -r win-x64 -c release

Once completed, you can find the native executable in the root folder of your project under /bin/x64//netcoreapp2.0/publish/

like image 51
AlbertK Avatar answered Oct 17 '22 21:10

AlbertK


Before .NET Core 3.0

dotnet publish -r win-x64 -c Release --self-contained

Pretty self explanatory:

  • Publish the project from the current directory.
  • Build the project to run on Windows 64 bit machines.
  • Build in release configuration mode
  • Publish everything as “self-contained” so that everything required to run the app is packaged up with our executable

So this works right, we end up with a folder that has our exe and everything that is required to run it, but the issue is that there is a tonne required to run even a HelloWorld console app.

Publish folder

After .NET Core 3.0

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

All this does is runs our publish command but tells it to package it within a single file. You’ll notice that we no longer specify the self-contained flag. That’s because it’s assumed that if you are packaging as a single exe, that you will want all it’s dependencies along with it. Makes sense.

Publish folder

A single tidy exe! When this is executed, the dependencies are extracted to a temporary directory and then everything is ran from there. It’s essentially a zip of our previous publish folder! I’ve had a few plays around with it and honestly, it just works. There is nothing more to say about it. It just works.

File Size And Startup Cost

  • Keen eyes will notice something about the above screenshot. The file size. It’s over 70MB! That’s crazy for an application that does nothing but print Hello World to the screen! This is solved in Preview 6 of .NET Core 3.0 with a feature called IL Linker or Publish trimmer that omits DLL’s that aren’t used.
  • The other issue you may find is that there is a slight startup cost when running the self contained executable for the first time. Because it needs to essentially unzip all dependencies to a temporary directory on first run, that’s going to take a little bit of time to complete. It’s not crazy (5 seconds or so), but it’s noticeable. Luckily on subsequent runs it uses this already unzipped temp folder and so startup is immediate.

Modify the csproj and add PublishTrimmed = true.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>

    <OutputType>Exe</OutputType>

    <TargetFramework>netcoreapp3.0</TargetFramework>

    <PublishTrimmed>true</PublishTrimmed>

  </PropertyGroup>

</Project>

Now run the below command:

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

Reference:

  1. https://dotnetcoretutorials.com/2019/06/20/publishing-a-single-exe-file-in-net-core-3-0/
  2. https://www.hanselman.com/blog/MakingATinyNETCore30EntirelySelfcontainedSingleExecutable.aspx
like image 45
Gopi Avatar answered Oct 17 '22 22:10

Gopi


This documentation from Microsoft uses the same dotnet publish -c Release -r win10-x64 that you have used, and documents it as follows (emphasis added):

This creates a Release (rather than a Debug) version of your app for each target platform. The resulting files are placed in a subdirectory named publish that's in a subdirectory of your project's .\bin\Release\netcoreapp1.1 subdirectory. Note that each subdirectory contains the complete set of files (both your app files and all .NET Core files) needed to launch your app.

Along with your application's files, the publishing process emits a program database (.pdb) file that contains debugging information about your app. The file is useful primarily for debugging exceptions. You can choose not to package it with your application's files. You should, however, save it in the event that you want to debug the Release build of your app.

So the correct files to deploy are the ones in the publish subdirectory. That directory is 60+ MB because it includes the .NET core libraries needed for self-contained deployment.

like image 2
pmcoltrane Avatar answered Oct 17 '22 21:10

pmcoltrane