你使用 ILMerge 吗?您是否使用 ILMerge 合并多个程序集以简化 dll 的部署?在 ILMerging 程序集在一起之后,您是否发现生产中的部署/版本控制问题?
我正在寻找一些关于使用 ILMerge 减少部署摩擦的建议,如果这可能的话。
你使用 ILMerge 吗?您是否使用 ILMerge 合并多个程序集以简化 dll 的部署?在 ILMerging 程序集在一起之后,您是否发现生产中的部署/版本控制问题?
我正在寻找一些关于使用 ILMerge 减少部署摩擦的建议,如果这可能的话。
我将 ILMerge 用于几乎所有不同的应用程序。我将它直接集成到发布构建过程中,所以我最终得到的是每个应用程序一个 exe,没有额外的 dll。
您不能 ILMerge 任何具有本机代码的 C++ 程序集。您也不能 ILMerge 任何包含 WPF 的 XAML 的程序集(至少我没有取得任何成功)。它在运行时抱怨找不到资源。
我确实为 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 文件完好无损。
要使用,请将其粘贴到您的Post Build
步骤中,在Build Events
C# 项目的选项卡下,并确保将第一行中的路径调整为指向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
我们在 Microsoft 应用程序块上使用 ILMerge - 而不是 12 个单独的 DLL 文件,我们有一个可以上传到客户区域的文件,而且文件系统结构更加整洁。
合并文件后,我必须编辑visual studio项目列表,删除12个单独的程序集并添加单个文件作为参考,否则它会抱怨找不到特定的程序集。我不太确定这将如何在后期部署中发挥作用,但值得一试。
我知道这是一个老问题,但我们不仅使用 ILMerge 来减少依赖项的数量,而且还内化了实用程序使用的“内部”依赖项(例如 automapper、restsharp 等)。这意味着它们被完全抽象出来,使用合并实用程序的项目不需要知道它们。这再次减少了项目中所需的引用,并允许它在需要时使用/更新同一外部库的自己的版本。
我们在很多项目中使用 ILMerge。例如,Web Service Software Factory会生成 8 个程序集作为其输出。我们将所有这些 DLL 合并到一个 DLL 中,以便服务主机只需引用一个 DLL。
它使生活变得更轻松,但这也不是什么大问题。
我们在组合 WPF 依赖项时遇到了同样的问题.... ILMerge 似乎没有处理这些问题。然而,Costura.Fody 为我们工作得非常好,花了大约 5 分钟才开始……一次非常好的体验。
只需使用 Nuget 安装(在包管理器控制台中选择正确的默认项目)。它将自己引入目标项目,默认设置立即为我们工作。
它合并所有标记为“Copy Local”= true 的 DLL,并生成一个合并的 .EXE(与标准输出一起),它的大小被很好地压缩(远小于总输出大小)。
许可证是 MIT,因此您可以根据需要修改/分发。
请注意,对于 Windows GUI 程序(例如 WinForms),您需要使用 /target: winexe开关。
/target: exe开关创建一个合并的控制台应用程序。
我刚刚开始使用 ILMerge 作为我的 CI 构建的一部分,将许多细粒度的 WCF 合同组合到一个库中。它工作得很好,但是新合并的库不能轻易地与其组件库或依赖于这些组件库的其他库共存。
如果在一个新项目中,您既引用了 ILMerged 库,又引用了依赖于您提供给 ILMerge 的输入之一的旧库,您会发现无法将 ILMerged 库中的任何类型传递给遗留库而不进行某种类型映射(例如自动映射器或手动映射)。这是因为一旦所有内容都编译完毕,类型就会有效地使用程序集名称进行限定。
名称也会发生冲突,但您可以使用extern alias修复它。
除非您确定您的合并程序集不会也永远不会依赖于同一库的独立版本。
在合并具有相同命名空间中的资源的 DLL 时,我们遇到了问题。在合并过程中,资源名称空间之一被重命名,因此无法找到资源。也许我们只是在那里做错了什么,仍在调查这个问题。
我们刚刚开始在我们的解决方案中使用 ILMerge,这些解决方案在我们的其他项目中重新分发和使用,到目前为止效果很好。一切似乎都正常。我们甚至直接混淆了打包的程序集。
我们正在考虑对 MS 企业库程序集执行相同的操作。
我看到的唯一真正的问题是包中各个程序集的版本控制。
我最近遇到了问题,我在程序集中合并了程序集,我有一些类是通过 Umbraco 开源 CMS 中的反射调用的。
通过反射进行调用的信息取自 db 表,该表具有实现和接口的类的程序集名称和命名空间。问题是当 dll 被合并时反射调用会失败,但是如果 dll 是分开的,它一切正常。我认为问题可能类似于 longeasy 的问题?
在我看来,#1 ILMerge 最佳实践是不要使用 ILMerge。相反,使用SmartAssembly。原因之一是 #2 ILMerge 最佳实践是在执行 ILMerge 后始终运行 PEVerify,因为 ILMerge 不保证它将正确地将程序集合并到有效的可执行文件中。
ILMerge 的其他缺点:
另一个值得关注的工具是 Mono.Cecil 和 Mono.Linker [2] 工具。
[2]:http://www.mono-project.com/Linker