.NET的Windows应用程序可以压缩成单个.exe文件吗?

36
我不太熟悉使用Visual Studio 2005的.NET桌面应用程序。是否可以将整个应用程序运行在单个.exe文件中?

3
你是想同时摆脱用户需要安装 .Net 框架的需求,还是只想将几个 DLL 文件与主 .exe 文件链接在一起? - Joel Coehoorn
13个回答

34

很遗憾,这个包已经被弃用了。 - Aleksey Pavlov

16

现在,已经是2015年了,您可以使用Costura.Fody来实现这个功能。使用它只需要将NuGet包添加到您的项目中并重新编译即可。我不确定它是否适用于Visual Studio 2005,因为那时还没有到2008年。但是我在几个项目中使用过它,效果非常好。

Fody是一个通用的代码编织器,它是免费且开源的。其基本思想是允许对编译后的.NET代码进行后处理,以增强其功能。例如,可以在每个方法调用中添加日志等功能。在我们的情况下,它将依赖的DLL文件打包到程序集资源中,以便在程序运行时加载它们,就像它们是独立的依赖项一样。


现在,dotnet Core已经自带了单个exe选项,因此Fody开发人员不再进行积极维护。 - er.bhargav.vyas

7
是的,在.NET中,您可以将整个应用程序封装为一个单独的EXE文件。只需确保您的解决方案只有一个Windows应用程序项目(以及除安装程序之外的任何其他项目)。
由.NET项目创建的EXE文件不会成为独立的可执行文件,但它唯一的依赖项将是.NET运行时(除非您添加对其他DLL程序集的引用)。如果您使用.NET 2.0(我建议这样做),则运行时将预安装在较新的PC上,并且在旧机器上设置非常简单和快速(安装程序约为23 MB)。
如果您的应用程序确实需要引用其他程序集(如数据访问DLL或.NET类库DLL项目),则可以使用其他帖子中引用的工具之一将您的EXE和所有引用的DLL组合到一个单独的EXE文件中。然而,传统做法指示只需部署EXE文件以及任何依赖的DLL作为单独的文件。在.NET中,依赖DLL的部署非常简单:只需将它们放在客户端计算机上与EXE文件相同的文件夹中即可。
推荐使用单文件安装程序(setup.EXE或setup.MSI)作为您的应用程序(无论是一个文件还是多个文件)的部署方式。.NET附带了可轻松创建安装程序的部署项目模板。
略有偏题:您可以使用NGEN将.NET应用程序编译为本地EXE,但它仍然依赖于.NET运行时。本地编译的优点是某些内容可以预编译,但我从未见过这种微小的性能提升值得麻烦的情况。

2
这个答案实际上没有回答问题,问题是如何将多个程序集合并成一个。 - Peter Duniho

5

现在是2021年,对此的支持已经取得了巨大的进步。

如果你已经使用.NET 5(它支持Windows Forms!),那么你可以创建一个单文件exe,甚至可以嵌入本地二进制文件。你必须从命令行运行发布命令,但它将生成一个单独的exe文件,并将任何配置或内容文件与之一起。目标机器上不需要安装dotnet sdk。

dotnet.exe publish YourProject.csproj -f net5.0 -o package/win-x64 -c Release -r win-x64 /p:PublishTrimmed=true /p:TrimMode=Link /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true

一些注意事项:

  • PublishTrimmed 可以设置为 false,以避免在反射使用较多的情况下进行代码删除。
  • TrimMode 可以设置为 copyusedlink。更多详细信息请参见:https://learn.microsoft.com/en-us/dotnet/core/deploying/trim-self-contained
  • -f 参数指定框架版本,即 net5.0 等。
  • -c 参数是配置,通常为 Release
  • -r 参数是要构建的运行时,可以是 win-x86win-x64linux-x64。也可能有 ARM 的选项。
  • -o 参数是输出文件夹。

完整参考文档:https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish


4

有一个叫做.NET Reactor的第三方工具可以帮助您实现此目的。我没有使用过该工具,所以不确定它的工作效果如何。


1
Reactor是一种代码混淆工具。在某些情况下,它可能会合并程序集,但这绝不是其主要目的,而且代码混淆本身也存在问题。不应将其推荐为类似Fody、ILMerge等合并程序集的解决方案。 - Peter Duniho

4
我使用了.NETZ .NET开源可执行文件打包器,将EXE和DLL文件打包到单个EXE文件中。这里是如何将DLL文件打包到一个文件的命令行示例:
netz -s application.exe foo.dll bar.dll

1
嗨,我已经使用了Netz。但它无法处理未管理的依赖项。 - mrid
1
我也使用了一个不支持的Web服务。.NetZ非常好,有太多选项,但已经停止更新了。 - Zolfaghari

3

Jeffrey Richter在他的书摘中写道,可以注册一个带有应用程序域ResolveAssembly事件的回调方法,以使CLR在程序初始化期间找到第三方程序集和DLL文件:

AppDomain.CurrentDomain.AssemblyResolve += (sender, 
  args) => {
    String resourceName = "AssemblyLoadingAndReflection." +
    new AssemblyName(args.Name).Name + ".dll";
    using (var stream =       
      Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)){
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
      }
   };

免责声明:本人未使用过此功能。据我所知,客户端仍需要安装.NET框架。

1
这显然是Costura.Fody使用的方法,另一个答案中有描述:https://dev59.com/dHVC5IYBdhLWcg3w-mZO#32556235 - StayOnTarget

1
你可以尝试使用NBox工具。

َ


1

1
Phoenix只是一个混淆工具。它提供的唯一“合并”功能是重新分发(可能违反许可证)ILMerge工具。因此,这个答案实际上在任何有用的方面都不与推荐ILMerge本身的答案有所不同。 - Peter Duniho

1

我自己正在使用.netshrink,它正好符合您的需求。它将主要和额外的程序集(DLL文件)打包成一个可执行映像。

我已经使用它一年了,再也不会回到ILMerge(它总是在某个时候崩溃...)。

.netshrink main window from the product's page


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接