ILMerge最佳做法


72

您是否使用ILMerge?您是否使用ILMerge合并多个程序集以简化dll的部署?将组件合并在一起后,您是否发现生产中的部署/版本问题?

我正在寻找有关使用ILMerge来减少部署冲突的建议,如果可能的话。

Answers:


44

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

您不能将任何具有本机代码的C ++程序集合并。您也不能ILMerge包含XAML for WPF的程序集(至少我还没有成功)。它在运行时抱怨找不到资源。

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


您是如何做到该版本构建集成的?
Svish

@Svish-hanselman.com/ blog/…
肖恩·高夫

8
:下面是ILMerge + XAML潜在的解决方法richarddingwall.name/2009/05/14/...
scobi


2
@Lamar可以为ILMerge共享该包装器.exe吗?
佛罗伦萨

41

介绍

这篇文章展示了如何.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


1
您如何显示构建的输出?我在编写输出时遇到一个无声的问题。stackoverflow.com/questions/42301103/…–
octopusgrabbus

@octopusgrabbus在Visual Studio中,选择View.. Output,然后选择Build,它显示了编译器的命令行输出(包括上述步骤)。或者,将这些命令复制到.bat文件中,然后从DOS窗口运行它以查看输出。
Contango

10

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

合并文件后,我必须编辑Visual Studio项目列表,删除12个单独的组件,并添加单个文件作为参考,否则它会抱怨找不到特定的程序集。我不太确定这在后期部署中如何工作,值得尝试一下。


7

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


3

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

它使生活更轻松一些,但也没什么大不了的。


3

我们在组合WPF依赖项时遇到了同样的问题.. ILMerge似乎没有处理这些问题。Costura.Fody为我们完美地工作了,花了大约5分钟才开始……这是非常好的经历。

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

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

该许可证是MIT,因此您可以根据需要进行修改/分发。

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


3

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


1

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


1

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

如果在一个新项目中,您同时引用了ILMerged库和依赖于您向ILMerge提供的输入之一的旧式库,您将发现您无法将ILMerged库中的任何类型传递给ILMerged库中的任何方法。旧版库,无需进行某种类型的映射(例如,自动映射器或手动映射)。这是因为一旦编译完所有内容,这些类型就可以使用程序集名称进行有效限定。

名称也会冲突,但是您可以使用extern alias来解决。

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


0

到目前为止,我们才刚刚开始在我们的解决方案中使用ILMerge,这些解决方案已在其他项目中重新分发和使用。一切似乎都正常。我们甚至直接混淆了打包的程序集。

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

我看到的唯一真正的问题是软件包中各个组件的版本控制。


0

最近,我遇到一个问题,即我没有在程序集中加入程序集,而在Umbraco开源CMS中通过反射调用了一些类。

通过反射进行调用的信息来自具有表名,已实现的类和接口的db表。问题在于,当dll被il合并时,反射调用将失败,但是如果dll被分离,则一切正常。我认为问题可能类似于longeasy遇到的问题?


-2

在我看来,#1 ILMerge最佳做法是“不要使用ILMerge”。而是使用SmartAssembly。原因之一是#2 ILMerge最佳实践是在执行ILMerge之后始终运行PEVerify,因为ILMerge不保证它将正确地将程序集合并为有效的可执行文件。

ILMerge的其他缺点:

  • 合并时,它会剥离XML注释(如果我对此很在意,我会使用混淆工具)
  • 它不能正确处理创建相应的.pdb文件

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

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


“它不能正确处理创建相应的.pdb文件”-在什么情况下是真的?我看过ILMerge生成合并的pdb,并毫无问题地使用了它们。
scobi 2010年

当您要合并的任何程序集都没有.pdb时。此外,SmartAssembly可以正确处理WPF资源(例如BAML)。
user429921

与Smartassembly相比,ILMerge的一大优势是它将合并XML文档文件。自发布之日起,Smartassembly将不会执行此操作。-一个付费用户Smartassembly
卡梅伦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.