您是否使用ILMerge?您是否使用ILMerge合并多个程序集以简化dll的部署?将组件合并在一起后,您是否发现生产中的部署/版本问题?
我正在寻找有关使用ILMerge来减少部署冲突的建议,如果可能的话。
Answers:
我几乎将所有不同的应用程序都使用ILMerge。我已经将它集成到发行版本的构建过程中,因此最终得到的是每个应用程序一个exe,没有额外的dll。
您不能将任何具有本机代码的C ++程序集合并。您也不能ILMerge包含XAML for WPF的程序集(至少我还没有成功)。它在运行时抱怨找不到资源。
我确实为ILMerge编写了一个包装可执行文件,在其中传递了要合并的项目的启动exe名称和输出exe名称,然后它反映了相关程序集,并使用适当的命令行参数调用了ILMerge。现在,当我将新的程序集添加到项目中时,它变得容易得多,无需记住要更新构建脚本。
这篇文章展示了如何.exe + .dll files
用单个替换全部combined .exe
。它还可以使调试.pdb
文件保持完整。
这是Post Build String
使用.NET 4.0的Visual Studio 2010 SP1的基础。我正在建立包含所有sub.dll文件的控制台.exe。
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
AssemblyName.all.exe
”,该文件将所有子dll合并为一个.exe。ILMerge\
目录。您需要将ILMerge实用程序复制到解决方案目录中(以便可以分发源而不必担心记录ILMerge的安装),或更改此路径以指向ILMerge.exe所在的位置。如果您无法解决问题,请打开Output
,然后选择Show output from: Build
。检查Visual Studio实际生成的确切命令,并检查错误。
该脚本用.exe + .dll files
单个替换所有脚本combined .exe
。它还可以使调试.pdb文件保持不变。
要使用它,请将其粘贴到C#项目中选项卡Post Build
下的步骤Build Events
中,并确保将第一行中的路径调整为指向ILMerge.exe
:
rem Create a single .exe that combines the root .exe and all subassemblies.
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
rem Remove all subassemblies.
del *.dll
rem Remove all .pdb files (except the new, combined pdb we just created).
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).all.pdb.temp"
del *.pdb
ren "$(TargetDir)$(TargetName).all.pdb.temp" "$(TargetName).all.pdb"
rem Delete the original, non-combined .exe.
del "$(TargetDir)$(TargetName).exe"
rem Rename the combined .exe and .pdb to the original project name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0
View.. Output
,然后选择Build
,它显示了编译器的命令行输出(包括上述步骤)。或者,将这些命令复制到.bat
文件中,然后从DOS窗口运行它以查看输出。
我们在许多项目上使用ILMerge。例如,Web Service Software Factory会产生类似8个程序集的输出。我们将所有这些DLL合并到一个DLL中,以便服务主机仅需引用一个DLL。
它使生活更轻松一些,但也没什么大不了的。
我们在组合WPF依赖项时遇到了同样的问题.. ILMerge似乎没有处理这些问题。Costura.Fody为我们完美地工作了,花了大约5分钟才开始……这是非常好的经历。
只需使用Nuget进行安装(在Package Manager控制台中选择正确的默认项目)。它将自身介绍到目标项目中,默认设置立即为我们工作。
它将所有标记为“ Copy Local” = true的DLL合并,并生成一个合并的.EXE(与标准输出一起),压缩后的大小很好(远小于总输出大小)。
该许可证是MIT,因此您可以根据需要进行修改/分发。
请注意,对于Windows GUI程序(例如WinForms),您将需要使用/ target:winexe开关。
/ target:exe开关创建一个合并的控制台应用程序。
我刚开始使用ILMerge作为我的CI版本的一部分,以将许多细粒度的WCF合同合并到一个库中。它工作得很好,但是新合并的库不能轻松地与其组件库或依赖于这些组件库的其他库共存。
如果在一个新项目中,您同时引用了ILMerged库和依赖于您向ILMerge提供的输入之一的旧式库,您将发现您无法将ILMerged库中的任何类型传递给ILMerged库中的任何方法。旧版库,无需进行某种类型的映射(例如,自动映射器或手动映射)。这是因为一旦编译完所有内容,这些类型就可以使用程序集名称进行有效限定。
名称也会冲突,但是您可以使用extern alias来解决。
我的建议是避免在合并的程序集中包含合并程序集公开的任何公共可用的lib(例如,通过返回类型,方法/构造函数参数,字段,属性,泛型...),除非您确定知道该用户是您合并的程序集不会也不永远不会依赖同一库的独立版本。
在我看来,#1 ILMerge最佳做法是“不要使用ILMerge”。而是使用SmartAssembly。原因之一是#2 ILMerge最佳实践是在执行ILMerge之后始终运行PEVerify,因为ILMerge不保证它将正确地将程序集合并为有效的可执行文件。
ILMerge的其他缺点:
另一个值得关注的工具是Mono.Cecil和Mono.Linker [2]工具。
[2]:http:// www.mono-project.com/Linker