如何生成不包含 IL、JIT 和 metadata 的单个小型 .NET .exe 文件?
结论
如果你想只分发一个较小的 .exe,并使用目标机器上已安装的 .NET,可以选择框架依赖的单文件发布:
dotnet publish test.csproj -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true -p:DebugType=None -o ./publish-fdd
VB.NET 项目将 test.csproj 换成对应的 .vbproj。
这种方式不打包 .NET 运行时,应用本身仍包含 IL 和 metadata,执行时也仍会使用 JIT。PublishSingleFile 只负责打包文件,不会把托管代码转换成本机代码。微软单文件发布文档
如果还要求应用不以 IL 形式分发、运行时不使用 JIT,可以考虑 Native AOT。它会把所需的运行时组件编入程序,不使用目标机器上的共享 .NET 运行时。因此,这两组要求无法通过同一种标准发布配置同时满足。微软 Native AOT 文档
为什么会有多个文件,或者生成约 100 MB 的单文件?
普通构建输出中的 test.exe 通常是本机启动器,也叫 apphost,应用代码则位于 test.dll。如果只复制这个 .exe,或者删除旁边的文件,程序通常无法运行。.NET 发布方式说明
单文件发布会将应用程序集和运行配置合并到可执行文件中。如果同时选择自包含部署(self-contained),还会带上 .NET 运行时和框架库,文件体积也会大很多。题目中约 100 MB 的文件可能来自这种配置,需要检查发布设置和项目依赖才能确认。单文件发布与文件大小
JIT 是运行时的组件,普通应用程序集并不各自附带一个 JIT 编译器。框架依赖发布省去了随应用分发的运行时,应用执行时仍然需要目标机器上的运行时。
如何配置较小的单文件 .exe?
对于现代 .NET SDK 风格项目,可以在现有 .csproj 或 .vbproj 中加入以下属性,保留原来的目标框架和其他设置:
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<DebugType>none</DebugType>
</PropertyGroup>
然后执行发布命令:
dotnet publish -c Release -o ./publish-fdd
这些属性分别控制以下行为:
PublishSingleFile=true:启用单文件打包。SelfContained=false:使用目标机器上的 .NET 运行时。RuntimeIdentifier=win-x64:生成面向 Windows x64 的程序;其他平台或架构需要分别发布。DebugType=none:不为当前项目生成 PDB 调试符号,可用的调试信息也会相应减少。发布属性说明、DebugType 说明
发布结果位于 publish-fdd 目录。没有额外内容文件或本机依赖的简单项目,可以通过这种方式得到只需分发一个 .exe 的结果。复杂项目仍需检查输出目录,不能保证所有依赖都会自动合并。
“从 OS 加载 .NET DLL”需要什么前提?
程序需要使用目标机器上安装的兼容 .NET 运行时。现代 .NET 不保证随 Windows 自带,Windows 中已有的 .NET Framework 也不能直接替代现代 .NET Runtime。Windows 上的 .NET 安装说明
可以在目标机器上运行以下命令,检查已安装的运行时:
dotnet --list-runtimes
该命令列出当前 dotnet 架构可见的运行时,检查时还要确认 x86、x64 等架构是否与应用匹配。dotnet 命令说明
运行时类型也要与应用匹配:
- 普通控制台应用通常需要 .NET Runtime。
- WinForms、WPF 应用需要 .NET Desktop Runtime。
设置 SelfContained=false 不会让系统自动提供第三方 NuGet 包中的 DLL,应用自身的依赖仍需随应用部署。运行时类型说明、框架依赖部署说明
如果必须去掉 IL 和 JIT,如何使用 Native AOT?
如果目标框架、应用类型和依赖都支持 Native AOT,可以在单独的项目发布配置中添加:
<PropertyGroup>
<PublishAot>true</PublishAot>
</PropertyGroup>
这份配置中不要保留前面的 <SelfContained>false</SelfContained>。在满足 Windows 本机编译工具链要求的环境中执行:
dotnet publish -c Release -r win-x64 -o ./publish-aot
Native AOT 在发布时将 IL 编译成本机代码,运行时无需 JIT,也无需预装 .NET。程序仍会包含所需的运行时支持代码,例如垃圾回收相关组件,因此不能理解为完全没有运行时。Native AOT 发布步骤与限制
Native AOT 也不能保证完全没有 metadata。它仍可能保留反射、类型信息和堆栈跟踪所需的数据,这些数据与普通托管程序集中的完整 metadata 并不等同。.NET 本机编译器架构说明
使用前还需处理 AOT 和裁剪警告,尤其要检查动态程序集加载、System.Reflection.Emit 以及依赖反射的库。最终体积取决于实际使用的功能和依赖,无法保证固定大小。Windows 下额外生成的 .pdb 是调试符号,正常运行时通常无需分发,可以单独保存,用于排查问题。Native AOT 兼容性与调试信息
备注:内容仅供参考。
