我们有多种工具可以将程序集合并成为一个。比如 ILMerge、Mono.Merge。前者不可定制、运行缓慢、消耗资源(不过好消息是现在开源了);后者已被弃用、不受支持且基于旧版本的 Mono.Cecil。

而本文介绍用来替代它们的 ILRepack,使用 ILRepack 来合并程序集。


ILRepack 提供了可供你项目使用的 NuGet 包。如果你在团队项目当中安装了 ILRepack 的 NuGet 包,那么无论团队其他人是否安装了 ILRepack 的工具,都可以使用 ILRepack 工具。这可以避免要求团队所有成员安装工具或者将工具内置到项目的源代码管理中。

要以 NuGet 包的形式来使用 ILRepack,需要首先安装 ILRepack 的 NuGet 包:

  • [NuGet Gallery ILRepack](https://www.nuget.org/packages/ILRepack/)

或者直接在你的项目的 csproj 文件中添加 PackageReference:

我现在有一个项目 Walterlv.Demo.AssemblyLoading,这是一个控制台程序。这个程序引用了一个 NuGet 包 Ben.Demystifier。为此带来了三个额外的依赖。

- Walterlv.Demo.AssemblyLoading.exe- Ben.Demystifier.dll- System.Collections.Immutable.dll- System.Reflection.Metadata.dll

而我们可以使用 ILRepack 将这些依赖和我们生成的主程序合并成一个程序集,这样分发程序的时候只需要一个程序集即可。

那么,我们现在需要编辑我们的项目文件:

    <Project Sdk="Microsoft.NET.Sdk">        <PropertyGroup>            <OutputType>Exe</OutputType>            <TargetFramework>net48</TargetFramework>        </PropertyGroup>

        <ItemGroup>            <PackageReference Include="Ben.Demystifier" Version="0.1.4" />            <PackageReference Include="ILRepack" Version="2.0.17" />        </ItemGroup>++      <Target Name="ILRepack">++          <Exec Command="&quot;$(ILRepack)&quot; /out:$(OutputPath)$(AssemblyName).exe $(OutputPath)$(AssemblyName).exe $(OutputPath)Ben.Demystifier.dll $(OutputPath)System.Collections.Immutable.dll $(OutputPath)System.Reflection.Metadata.dll" />++      </Target>

    </Project>

我们只增加了三行,添加了一个名称为 ILRepack 的 Target。(注意到项目文件中我有额外引用一个其他的 NuGet 包 Ben.Demystifier,这是为了演示将依赖进行合并而添加的 NuGet 包,具体是什么都没有关系,我们只是在演示依赖的合并。)在这个 Target 里面,我们使用 Exec 的 Task 来执行 ILRepack 命令。具体这个命令代表的含义我们在下一节介绍 ILRepack 工具的时候会详细介绍。如果你希望在你的项目当中进行尝试,可以把后面那些代表程序集的名称改为你自己项目中依赖程序集的名称。

现在在编译的时候使用命令 msbuild /t:ILRepack 就可以完成程序集的合并了。

注意,你普通编译的话是不会进行 IL 合并的。

如果你希望常规编译也可以进行 IL 合并,或者说希望在 Visual Studio 里面点击生成按钮的时候也能完成 IL 合并的话,那么你还需要增加一个跳板的编译目标 Target。

我将这个名为 _ProjectRemoveDependencyFiles 的 Target 增加到了下面。它的目的是在 AfterBuild 这个编译目标完成之后(AfterTargets)执行,然后执行前需要先执行(DependsOnTargets)ILRepack 这个 Target。在这个编译目标执行的时候还会将原本的三个依赖删除掉,这样在生成的目录下我们将只会看到我们最终期望的程序集 Walterlv.Demo.AssemblyLoading.exe 而没有其他依赖程序集。

    <Project Sdk="Microsoft.NET.Sdk">        <PropertyGroup>            <OutputType>Exe</OutputType>            <TargetFramework>net48</TargetFramework>        </PropertyGroup>

        <ItemGroup>            <PackageReference Include="Ben.Demystifier" Version="0.1.4" />            <PackageReference Include="ILRepack" Version="2.0.17" />        </ItemGroup>

        <Target Name="ILRepack">            <Exec Command="&quot;$(ILRepack)&quot; /out:$(OutputPath)$(AssemblyName).exe $(OutputPath)$(AssemblyName).exe $(OutputPath)Ben.Demystifier.dll $(OutputPath)System.Collections.Immutable.dll $(OutputPath)System.Reflection.Metadata.dll" />        </Target>

++      <Target Name="_ProjectRemoveDependencyFiles" AfterTargets="AfterBuild" DependsOnTargets="ILRepack">++          <ItemGroup>++              <_ProjectDependencyFile Include="$(OutputPath)Ben.Demystifier.dll" />++              <_ProjectDependencyFile Include="$(OutputPath)System.Collections.Immutable.dll" />++              <_ProjectDependencyFile Include="$(OutputPath)System.Reflection.Metadata.dll" />++              </ItemGroup>++          <Delete Files="@(_ProjectDependencyFile)" />++      </Target>

    </Project>

最终生成的输出目录下只有我们最终期望生成的程序集:

相比于 ILMerge,ILRepack 的命令行在尽量贴近 ILMerge 的情况下做得更加简化了。

ilrepack /out:Walterlv.Demo.AssemblyLoading.exe Walterlv.Demo.AssemblyLoading.exe Ben.Demystifier.dll System.Collections.Immutable.dll System.Reflection.Metadata.dll

其中,/out 表示最终的输出程序集的名称或路径,后面没有前缀的参数都是需要合并的程序集的名称或路径。这些需要合并的参数中,第一个参数是主程序集,而后续其他的都是待合并的程序集。区别主程序集和其他程序集的原因是输出的程序集需要有名称、版本号等等信息,而这些信息将使用主程序集中的信息。

如果希望使用 ILRepack 的其他命令,可以考虑使用帮助命令:

或者直接访问 ILRepack 的 GitHub 仓库来查看用法:

  • gluck/il-repack: Open-source alternative to ILMerge

如果你在使用 ILRepack 合并程序集的过程中出现了缺少依赖的错误,例如下面这样:

Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'xxxxxxxxx'

那么你需要做以下两种事情中的任何一种:

  1. 将所有依赖合并;

  2. 将依赖加入搜索目录。

将所有依赖合并指的是将缺少的依赖也一起作为命令行参数传入要合并的程序集中。

而另一种是增加一个参数 /lib,即添加一个被搜索的依赖程序集的目录。将这个目录指定后,则可以正确解析依赖完成合并。而且这些依赖将成为合并后的程序集的依赖,不会合并到程序集中。

ilrepack /lib:D:\Dependencies /out:Walterlv.Demo.AssemblyLoading.exe Walterlv.Demo.AssemblyLoading.exe Ben.Demystifier.dll System.Collections.Immutable.dll System.Reflection.Metadata.dll

参考资料

  • gluck/il-repack: Open-source alternative to ILMerge

原文地址:https://blog.walterlv.com/post/merge-assemblies-using-ilrepack.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

.NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖相关推荐

  1. .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖

    我们有多种工具可以将程序集合并成为一个.打包成一个程序集可以避免分发程序的时候带上一堆依赖而出问题. ILMerge 可以用来将多个程序集合并成一个程序集.本文介绍使用 ILMerge 工具和其 Nu ...

  2. .NET 将多个程序集合并成单一程序集的 4+3 种方法

    编写 .NET 程序的时候,我们经常会在项目的输出目录下发现一大堆的文件.除了我们项目自己生成的程序集之外,还能找到这个项目所依赖的一大堆依赖程序集.有没有什么方法可以把这些依赖和我们的程序集合并到一 ...

  3. 未能加载文件或程序集“*****.dll”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。(异常来自HRESULT:0x80131040)

    未能加载文件或程序集"*****.dll"或它的某一个依赖项.找到的程序集清单定义与程序集引用不匹配.(异常来自HRESULT:0x80131040) 参考文章: (1)未能加载文 ...

  4. 未能加载文件或程序集“SqlServerDal”或它的某一个依赖项。系统找不到指定的文件。...

    今天遇到一个挺怪的问题,采用了工厂模式后,出去找不到程序集的问题: 未能加载文件或程序集"Tianyige.SqlServerDAL"或它的某一个依赖项.系统找不到指定的文件. 解 ...

  5. 【转】未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。...

    "/xxxxx"应用程序中的服务器错误.  -------------------------------------------------------------------- ...

  6. 未能加载文件或程序集“xxx”或它的某一个依赖项

    未能加载文件或程序集"xxx"或它的某一个依赖项.试图加载格式不正确的程序. 说明: 执行当前 Web 请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导 ...

  7. 未能加载文件或程序集“xxx”或它的某一个依赖项。试图加载格式不正确的程序。

    "未能加载文件或程序集"xxx"或它的某一个依赖项.试图加载格式不正确的程序."这个错误可能在IIS或VS中出现,一般是平台和dll版本不一致导致的. 一.VS ...

  8. 未能加载文件或程序集“XXX”或它的某一个依赖项。试图加载格式不正确的程序。(转)...

    未能加载文件或程序集"XXX"或它的某一个依赖项.试图加载格式不正确的程序. 作者: 字体:[增加 减小] 类型:转载 时间:2012-11-01 我要评论 如果你将应用程序生成x ...

  9. 【VS 2022】未能加载文件或程序集“sapnco”或它的某一个依赖项。试图加载格式不正确的程序。

    将开发工具 VS 2019 升级 到 VS 2022 之后,原来 的 MVC 3.0 项目启动的时候报错: 未能加载文件或程序集"sapnco"或它的某一个依赖项.试图加载格式不正 ...

最新文章

  1. linux管理用户和文件权限
  2. EOF的意义及用法(while(scanf(“%d“,n) != EOF))
  3. 学生开始学术生涯的好方法
  4. NLP将迎来黄金十年,7个案例带你入门(附Python代码)
  5. 如何反编译APK文件
  6. LTE:资源调度(5)
  7. 边缘检测(Laplace算子,LOG算子)
  8. PICkit4 烧写、仿真时获取ID失败 Reception on endpoint 129 failed
  9. [转]c#对象的浅拷贝和深拷贝
  10. 死链对网站的影响、产生过程、解决办法汇总
  11. python制作壁纸获取器exe,壁纸采集
  12. Edgy Trees CodeForces - 1139C
  13. 20180802 (个别内置方法)
  14. 做SEO为什么有的网站收录很难做?
  15. VBA操作WORD(三):设置页面
  16. 灰色的心情,贴几首我们一起唱的歌吧
  17. linux挂载cifs磁盘_CentOS7.4_1708挂载CIFS报错
  18. 大田智能灌溉系统解决方案
  19. ssm+java+vue微信小程序的驾校预约管理系统#毕业设计
  20. APE直接用Nero刻录成CD

热门文章

  1. 使用高级管理控制台获得对Windows Home Server的扩展访问
  2. 在数据库插入带小数点数据的问题
  3. Lucene5.5.4入门以及基于Lucene实现博客搜索功能
  4. NATS服务器部署及测试
  5. express 4 简单实现自动注册路由功能
  6. TortoiseSVN客户端重新设置用户名和密码[转]
  7. 恢复Ext3下被删除的文件
  8. iPhone比小米贵3000,贵在哪里?
  9. SQLServer支持大内存方案(转载)
  10. 无需Windbg | 使用VS 2019调试.NET程序的Crash异常