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

Posted

技术标签:

【中文标题】将 .NET Core 应用程序发布为可移植的可执行文件【英文标题】:Publish .NET Core App As Portable Executable 【发布时间】:2018-06-05 15:17:41 【问题描述】:

我有一个简单的 .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 文件。

我有一些问题:

exe 文件中的哪一个(发布文件夹内部/外部)我需要 PE 应用程序? 为什么当我剪切 exe 文件并将其移动到其他位置时它无法运行(没有消息)? 如果我需要所有 dll 文件来运行应用程序,那么我有两个选项(发布文件夹内部/外部),发布文件夹内部大小为 66 MB,而发布文件夹外部大小为 1 MB。 我想要一个exe 文件来运行我的程序,而不需要 dll 文件。

【问题讨论】:

尚不支持单个 EXE - 计划用于 .NET Core 3.0:blogs.msdn.microsoft.com/dotnet/2018/05/07/…For cases where the maximum isolation is required, you can deploy .NET Core with your application. We’re working on new build tools that will bundle your app and .NET Core together as in a single executable, as a new option. 感谢@karelzikmund,很好的回答。 github中有这个问题吗? 【参考方案1】:

.NET Core 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(感谢 Darien Shannon 在评论中提及)和dotnet CoreRT。两者都可以与以前版本的 .Net Core 一起使用

Warp

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

Dotnet CoreRT

截至 2022 年 1 月,此项目已被 dotnet/runtimelab 存储库中的 NativeAOT 实验所取代。感谢@t.j。

现在,您可以尝试使用dotnet CoreRT 项目将应用程序预编译为本机单文件可执行文件。我说“尝试”是因为文档 says:

该项目处于开发的早期阶段。

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

dotnet new nuget 

这会将 nuget.config 文件添加到您的应用程序。打开文件 并在下面的元素中添加以下内容:

<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

完成后,您可以在根文件夹中找到本机可执行文件 /bin/x64//netcoreapp2.0/publish/下你的项目的

【讨论】:

只想提一下warp是一个类似于ILMerge的工具,可以用dotnet核心应用创建“自包含的单一二进制应用程序”。 它还将把原本应该是 135kb 的 cli 工具变成 35MB 的 cli 工具 有类似dotnet publish -r current -c release 的东西吗?我想发布当前操作系统的可执行文件,并可能将其添加到 csproj。调用可执行文件比依赖 dotnet CLI 调用 dll 容易得多 注意:From the CoreRT team:“这个项目 [CoreRT] 是 superseded by NativeAOT dotnet/runtimelab repo 中的实验”【参考方案2】:

.NET Core 3.0 之前

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

不言自明:

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

所以这很正常,我们最终得到一个文件夹,其中包含我们的 exe 和运行它所需的一切,但问题是即使是运行 HelloWorld 控制台应用程序也需要大量的资源。

.NET Core 3.0 之后

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

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

一个整洁的 exe!执行此操作时,将依赖项提取到临时目录,然后从那里运行所有内容。它本质上是我们之前发布文件夹的压缩包!我已经玩了一些游戏,老实说,它确实有效。没有什么可说的了。它只是工作。

文件大小和启动成本

敏锐的眼睛会注意到上面的截图。文件大小。超过70MB!这对于一个只在屏幕上打印 Hello World 的应用程序来说太疯狂了!这在 .NET Core 3.0 的 Preview 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

参考

    https://dotnetcoretutorials.com/2019/06/20/publishing-a-single-exe-file-in-net-core-3-0/ https://www.hanselman.com/blog/MakingATinyNETCore30EntirelySelfcontainedSingleExecutable.aspx

【讨论】:

win-x64 是硬编码的。我有一个为当前操作系统发布的“自动”,无论它用于构建 参考original design document for single-file publishing 也可能很有用,它仍然是我能找到的最接近微软官方文档的地方,但似乎没有被谷歌索引,因此如果你不知道在哪里寻找它。【参考方案3】:

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

这会为每个目标平台创建应用的发布(而不是调试)版本。 生成的文件放在一个 名为 publish 的子目录,位于项目的子目录中 .\bin\Release\netcoreapp1.1 子目录。 注意 每个子目录都包含完整的文件集(您的 应用程序文件和所有 .NET Core 文件)启动您的应用程序。

与您的应用程序的文件一起,发布过程会发出一个 包含有关调试信息的程序数据库 (.pdb) 文件 你的应用程序。该文件主要用于调试异常。你 可以选择不将其与您的应用程序文件打包。你 但是,如果您想调试 发布您的应用的构建版本。

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

【讨论】:

以上是关于将 .NET Core 应用程序发布为可移植的可执行文件的主要内容,如果未能解决你的问题,请参考以下文章

将 HttpModule .Net 类库移植到 .Net Core Web API

将 WCF 应用程序从 .Net 框架转换为 .Net Core 时如何移植 <system.serviceModel> 配置?

在 Visual Studio 2017 中将 .NET Core 2.2 应用程序发布为依赖于框架的可执行文件 (FDE)

在.NET Core中使用MEF

从 ASP.NET MVC 5 移植到 dotnet core 2:可能替代 System.Web.Mvc.HttpStatusCodeResult [重复]

打包.NET Core的程序到一个单独的可执行文件