将 .NET Core 应用发布为可移植的可执行文件

Publish .NET Core App As Portable Executable

我有一个简单的 .net 核心应用程序并通过以下命令发布它:

 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>

当发布过程完成时,dotnet 在 bin\Release 文件夹中创建 win10-x64 文件夹,然后在打开它后文件夹包含 publish 文件夹和一些 dll 和 exe 文件。

我遇到了一些问题:

Microsoft 的

This documentation 使用与您使用的相同的 dotnet publish -c Release -r win10-x64,并将其记录如下(重点添加):

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.

因此要部署的正确文件是 publish 子目录中的文件。该目录超过 60 MB,因为它包含独立部署所需的 .NET 核心库。

.NET 核心 3.0

.NET Core 3.0 开箱即用。它将所有内容打包在一个 .exe 文件中(基本控制台应用程序约 68 MB)。有一个 PublishTrimmed=true 选项可以通过分析静态代码引用并从最终构建中排除未使用的框架程序集来将大小减小到 ~28 MB。

要配置 single exe 构建编辑您的 csproj 文件:

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

在命令行上的文件夹中 csproj 文件:

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

有关详细信息,请参阅 Gopi 给出的一个很好的答案。

独立实用程序

Warp (thanks to Darien Shannon for mentioning it in the comment) and dotnet CoreRT。两者都适用于以前版本的 .Net Core

Warp

这是一个类似于ILMerge的经典工具.NET Framework。这是非常容易使用。对于基本的控制台应用程序,它可以产生 .exe ~35 MB 没有 tree shaker 和大约 10-15 MB 有 tree shaker。

Dotnet CoreRT

自 2022 年 1 月起,该项目已被 dotnet/runtimelab 回购中的 NativeAOT 实验所取代。感谢@t.j.

现在,您可以尝试使用 dotnet CoreRT project. I'm saying "try" because documentation says:

将应用程序预编译为本机单文件可执行文件

This project is in the early stages of its development.

尽管如此,它至少适用于简单的应用程序。请参阅示例 here。 根据它的描述,你需要在项目文件夹中运行以下命令:

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" />

然后运行这个:

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

然后运行这个:

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/

.NET Core 3.0 之前

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

不言自明:

  • 从当前目录发布项目。
  • 在 Windows 64 位机器上将项目构建到 运行。
  • 在发布配置模式下构建
  • 将所有内容发布为“self-contained”以便 运行 该应用程序与我们的可执行文件打包在一起

所以这工作正常,我们最终得到一个文件夹,里面有我们的 exe 和 运行 它所需的一切,但问题是 运行 甚至需要一吨HelloWorld 控制台应用程序。

.NET Core 3.0 之后

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

所有这一切都是 运行 我们的发布命令,但告诉它将它打包在一个文件中。您会注意到我们不再指定 self-contained 标志。那是因为假定如果您将其打包为单个 exe,那么您将需要它的所有依赖项。有道理。

一个整洁的 exe!执行此操作时,依赖项将被提取到一个临时目录,然后所有内容都是 运行。它本质上是我们之前发布文件夹的一个压缩包!我玩过几次,老实说,它很管用。对此无话可说。它只是工作。

文件大小和启动成本

  • 敏锐的眼睛会注意到上面的截图。文件大小。超过70MB!对于一个只在屏幕上打印 Hello World 什么都不做的应用程序来说,这太疯狂了!这在 .NET Core 3.0 的预览版 6 中得到了解决,它具有称为 IL Linker 或 Publish trimmer 的功能,可以省略未使用的 DLL。
  • 您可能会发现的另一个问题是 运行首次使用自包含的可执行文件时,启动成本很小。因为它需要先将所有依赖项解压缩到一个临时目录 运行,这将需要一点时间才能完成。这并不疯狂(5 秒左右),但很明显。幸运的是,在随后的 运行 中,它使用这个已经解压的临时文件夹,因此可以立即启动。

修改csproj并添加PublishTrimmed = true。

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

  <PropertyGroup>

    <OutputType>Exe</OutputType>

    <TargetFramework>netcoreapp3.0</TargetFramework>

    <PublishTrimmed>true</PublishTrimmed>

  </PropertyGroup>

</Project>

现在运行下面的命令:

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

参考

  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