Search code examples
c#.net-corepublishportable-executableself-contained

Publish a .NET Core application as a portable executable (PE)


I have a simple .NET Core application and publish it by the 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 the publish process finished, dotnet created a win10-x64 folder in the bin\Release folder. Then after opening it, the folder contains a publish folder and some DLL and EXE files.

There are some issues for me:

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

Folder Size Image


Solution

  • .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 application). 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 a 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 a csproj file:

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

    For more details, see the great answer given by Gopi.

    Stand-alone utilities

    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 repository. 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/