ILMerge最佳实践

时间:2008-08-13 01:05:47

标签: c# .net deployment ilmerge

你使用ILMerge吗?您是否使用ILMerge合并多个程序集以简化dll的部署? ILMerging组装后,您是否在生产中发现了部署/版本控制问题?

我正在寻找一些关于使用ILMerge来减少部署摩擦的建议,如果可能的话。

12 个答案:

答案 0 :(得分:41)

我将ILMerge用于几乎所有不同的应用程序。我已将它集成到发布版本构建过程中,因此我最终得到的是每个应用程序的一个exe,没有额外的dll。

您无法ILMerge任何具有本机代码的C ++程序集。 您也无法ILMerge包含XFL for WPF的任何程序集(至少我没有取得任何成功)。它在运行时抱怨无法找到资源。

我确实为ILMerge编写了一个包装器可执行文件,我在其中传递了我要合并的项目的启动exe名称和输出exe名称,然后它反映了依赖程序集并使用适当的命令行参数调用ILMerge。当我向项目添加新程序集时,现在要容易得多,我不必记得更新构建脚本。

答案 1 :(得分:40)

简介

这篇文章展示了如何用一个.exe + .dll files替换所有combined .exe。它还使调试.pdb文件保持不变。

对于控制台应用

以下是使用.NET 4.0的Visual Studio 2010 SP1的基本Post Build String。我正在构建一个包含所有子.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

答案 2 :(得分:10)

我们在Microsoft应用程序块上使用ILMerge - 而不是12个单独的DLL文件,我们有一个文件可以上传到我们的客户区,而且文件系统结构很简单。

合并文件后,我不得不编辑visual studio项目列表,删除12个单独的assmeblies并添加单个文件作为参考,否则会抱怨它无法找到特定的程序集。我不太确定这在部署后的效果如何,值得一试。

答案 3 :(得分:6)

我知道这是一个老问题,但我们不仅使用ILMerge来减少依赖项的数量,而且还内化了该实用程序使用的“内部”依赖项(例如,automapper,restsharp等)。这意味着它们被完全抽象掉了,使用合并实用程序的项目不需要知道它们。这再次减少了项目中所需的引用,并允许它在需要时使用/更新自己版本的相同外部库。

答案 4 :(得分:3)

我们在很多项目中使用ILMerge。 Web Service Software Factory例如产生类似8个程序集的输出。我们将所有这些DLL合并到一个DLL中,这样服务主机只需要引用一个DLL。

它让生活变得更轻松,但也不是什么大事。

答案 5 :(得分:3)

我们在组合WPF依赖项时遇到了同样的问题.... ILMerge似乎没有处理这些问题。然而,Costura.Fody对我们来说非常完美,花了大约5分钟才开始......这是一次非常好的体验。

只需使用Nuget进行安装(在Package Manager控制台中选择正确的默认项目)。它将自身引入目标项目,默认设置立即为我们工作。

它合并标记为" Copy Local"的所有DLL。 = true并生成合并的.EXE(与标准输出一起),其大小压缩得很好(远小于总输出大小)。

许可证是麻省理工学院,因此您可以根据需要修改/分发。

https://github.com/Fody/Costura/

答案 6 :(得分:3)

请注意,对于Windows GUI程序(例如WinForms),您将要使用/ target: winexe 开关。
/ target: exe 开关创建合并的控制台应用程序。

答案 7 :(得分:1)

在合并具有相同命名空间中的资源的DLL时,我们遇到了问题。在合并过程中,重命名了一个资源名称空间,因此无法找到资源。也许我们只是在那里做错了,还在调查这个问题。

答案 8 :(得分:0)

我刚刚开始使用ILMerge作为我的CI构建的一部分,将许多细粒度的WCF合同合并到一个库中。它工作得很好,但是新的合并lib不能轻易地与其组件库或依赖于这些组件库的其他库共存。

如果在一个新项目中,你引用了ILMerged lib以及依赖于你给ILMerge的一个输入的遗留库,你会发现你不能将任何类型从ILMerged lib传递给遗留库中的任何方法,无需进行某种类型的映射(例如,自动映射或手动映射)。这是因为一旦编译了所有内容,就会使用程序集名称对类型进行有效限定。

名称也会发生冲突,但您可以使用extern alias修复此问题。

我的建议是避免在你的合并程序集中包含你的合并程序集公开的任何公开可用的lib(例如通过返回类型,方法/构造函数参数,字段,属性,泛型......),除非你确定知道合并程序集的用户不会也不会依赖于同一个库的独立版本。

答案 9 :(得分:0)

我最近遇到的问题是我在程序集中进行了组装,我有一些类,这些类是通过Umbraco opensource CMS中的反射来调用的。

通过反射进行调用的信息来自db表,该表具有程序集名称和实现的类的名称空间以及接口。问题是当dll合并时反射调用会失败,但是如果dll是独立的,那么一切正常。我认为问题可能类似于长寿所带来的问题?

答案 10 :(得分:0)

我们刚刚开始在我们的解决方案中使用ILMerge,这些解决方案在我们的其他项目中被重新分发并使用,到目前为止一直很好。一切似乎都运转正常。我们甚至直接模糊了打包的组件。

我们正在考虑对MS Enterprise Library程序集进行相同的操作。

我看到的唯一真正的问题是从包中对单个程序集进行版本控制。

答案 11 :(得分:-1)

在我看来,#1 ILMerge最佳实践就是不要使用ILMerge。相反,请使用SmartAssembly。其中一个原因是#2 ILMerge最佳实践是在执行ILMerge后始终运行PEVerify,因为ILMerge不保证它会将程序集正确地合并到有效的可执行文件中。

其他ILMerge缺点:

  • 合并时,它会删除XML注释(如果我关心这个,我会使用混淆工具)
  • 它无法正确处理创建相应的.pdb文件

值得关注的另一个工具是Mono.Cecil和Mono.Linker [2]工具。

[2]:http://www.mono-project.com/Linker