如何将ILMerge集成到Visual Studio生成过程中以合并程序集?


77

我想将一个.NET DLL程序集和一个VB.NET控制台应用程序项目引用的一个C#类库项目合并到一个命令行控制台可执行文件中。

我可以从命令行使用ILMerge做到这一点,但是我想将参考程序集和项目的这种合并集成到Visual Studio项目中。从我的阅读中,我了解我可以通过MSBuild任务或Target来完成此任务,只需将其添加到C#/ VB.NET Project文件中,但是由于MSBuild是大型主题,因此找不到具体示例。此外,我找到了一些将ILMerge命令添加到构建后事件的参考。

  1. 如何将ILMerge集成到只是MSBuild项目的Visual Studio(C#/ VB.NET)项目中,以将所有引用的程序集(copy-local = true)合并到一个程序集中?

  2. 这如何绑定到可能的ILMerge.Targets文件中?

  3. 使用构建后事件更好吗?


您还可以使用“后生成字符串”要做到这一点提到[这里] [1] [1]:stackoverflow.com/questions/2961357/...
扎因·阿里

Answers:


64

MSBuild ILMerge任务”(或MSBuild.ILMerge.Task)NuGet软件包使此过程非常简单。默认情况下,将所有“复制本地”引用合并到您的主程序集中。

注意:尽管这些软件包的名称相似,但与ILMerge.MSBuild.TasksDavide Icardi在回答中提到的。我在这里建议的是2014年8月首次发布。


3
应该的解决方案!+1

1
这应该是公认的解决方案。使其真正无痛。谢谢!
阿列克·戴维斯

不错的一个:D不完美,因为它“忘记了”在输出目录中包括额外的文件,但仍然不错^^
Ethenyl 2015年

1
效果非常好:包括包,构建,您就完成了!它带有图标。
雷姆科

1
我找不到MSBuild ILMerge的任何文档,该如何使用?有人有示例或说明吗?
MrDysprosium

19

这里是一个替代解决方案:

1)从nuget安装ILMerge.MSBuild.Tasks包

PM>安装包ILMerge.MSBuild.Tasks

2)通过添加以下代码,编辑要合并的项目的* .csproj文件:

  <!-- Code to merge the assemblies into one:setup.exe -->
  <UsingTask TaskName="ILMerge.MSBuild.Tasks.ILMerge" AssemblyFile="$(SolutionDir)\packages\ILMerge.MSBuild.Tasks.1.0.0.3\tools\ILMerge.MSBuild.Tasks.dll" />
  <Target Name="AfterBuild">
    <ItemGroup>
      <MergeAsm Include="$(OutputPath)$(TargetFileName)" />
      <MergeAsm Include="$(OutputPath)LIB1_To_MERGE.dll" />
      <MergeAsm Include="$(OutputPath)LIB2_To_MERGE.dll" />
    </ItemGroup>
    <PropertyGroup>
      <MergedAssembly>$(ProjectDir)$(OutDir)MERGED_ASSEMBLY_NAME.exe</MergedAssembly>
    </PropertyGroup>
    <Message Text="ILMerge @(MergeAsm) -&gt; $(MergedAssembly)" Importance="high" />
    <ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" />
  </Target>

3)像往常一样建立您的项目。


这个软件包没有更好地维护,这确实是一个陷阱。我一直在使用它,但是它缺少设置TargetPlatform的功能,这对.NET 4.5 / .NET 4.0兼容很重要。
伊恩·坎贝尔2013年

@davidlcardi我如何替换目标文件名,dll_to_merge等
Smith Smith

@Smith TargetFileName已经是msbuild变量,因此您无需替换它。LIB1_To_Merge.dll是固定名称。也许使用一些更复杂的msbuild脚本,您可以找到所有引用的程序集,但是我不知道该怎么做。
Davide Icardi 2013年

@DavideIcardi请让我看看您是否可以回应此stackoverflow.com/questions/15588086/…–
Smith Smith

1
有没有办法以某种方式使用我的密钥文件来使该符号成为我的装配体?
Steven Lemmens

18

一些可能对实施Scott Hanselman解决方案的人有用的更多信息

当我第一次设置它时,它会抱怨无法解析对System.Core等的引用。这与.NET 4支持有关。包括指向.NET 4 Framework目录的/ lib自变量即可对其进行修复(实际上只包含$(MSBuildBinPath))。

/lib:$(MSBuildBinPath)

然后,我发现IlMerge在合并时会挂起。它使用了一些CPU和大量RAM,但未输出任何内容。我当然找到了解决stackoverflow的方法

/targetplatform:v4

我还发现,Scott的博客文章中使用的某些MSBuild属性依赖于从项目目录执行MsBuild,因此我对其进行了一些调整。

然后,我将目标&ilmerge.exe移到了源代码树的tools文件夹中,这需要对路径进行另一个小的调整。

我最终得到以下Exec元素,以替换Scott的原始文章中的元素:

<Exec Command="&quot;$(MSBuildThisFileDirectory)Ilmerge.exe&quot; /lib:$(MSBuildBinPath) /targetplatform:v4 /out:@(MainAssembly) &quot;$(MSBuildProjectDirectory)\@(IntermediateAssembly)&quot; @(IlmergeAssemblies->'&quot;%(FullPath)&quot;', ' ')" /> 

更新 我还发现,如果使用Nuget包,则Logic Labs的答案是保持CopyLocal行为,并仅从CopyLocal中排除ilMerged程序集。否则,您需要为未合并的引用程序集的每个程序包目录指定一个/ lib参数。


实际上,我最终下载了ILMerge.exe,将其添加到源代码管理中,并向构建后事件中写入了一些命令
Haobo


9

我在以下文章中发现了一个问题:http : //www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx

如果您有不希望使用ILMerge的引用,那么本文中的代码将失败,因为它会覆盖默认的CopyLocal行为,而不执行任何操作。

解决此问题-而不是:

<Target Name="_CopyFilesMarkedCopyLocal"/> 

而是将此条目添加到目标文件中(仅.NET 3.5)(以过滤掉非无效的copylocal文件,并将它们视为正常文件)

<Target Name="AfterResolveReferences">
    <Message Text="Filtering out ilmerge assemblies from ReferenceCopyLocalPaths" Importance="High" />
    <ItemGroup>
        <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.IlMerge)'=='true'" />
    </ItemGroup>
</Target>

1
哦,是的!如果您使用的是Nuget,则肯定需要这样做,否则,您必须指定未合并的每个引用程序集的包内容文件夹。谢谢!
杰森·达菲特

4

这是一篇很棒的文章,将向您展示如何将引用的程序集合并到输出程序集中。它确切显示了如何使用msbuild合并程序集。


1
容易忽略他的更新且更详细的博客文章,因此在这里我将引用它clariusconsulting.net/blogs/kzu/archive/2009/02/23/…
2010年

我引用的文章较新,但不那么详细,但有一些有趣的评论。
罗汉·西

@WernerCD编辑了答案,以通过Internet存档提供固定链接。这是第二个
takrl

1

我的2美分-我收到@Jason的回复,并使其适用于我的解决方案,在该解决方案中,我想在bin / Debug文件夹中生成* .exe,而所有* .dll都位于同一文件夹中。

<Exec Command="&quot;$(SolutionDir)packages\ILMerge.2.13.0307\Ilmerge.exe&quot; /wildcards /out:&quot;$(SolutionDir)..\$(TargetFileName)&quot; &quot;$(TargetPath)&quot; $(OutDir)*.dll" /> 

注意:该解决方案显然已硬编码到ILMerge nuget软件包版本中。如果您有任何改进建议,请告诉我。


1

通过添加以下代码,编辑要合并的项目的* .csproj文件:

<Target Name="AfterBuild" Condition=" '$(ConfigurationName)' == 'Release' " BeforeTargets="PostBuildEvent">
  <CreateItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)'=='.dll'">
    <Output ItemName="AssembliesToMerge" TaskParameter="Include" />
  </CreateItem>
  <Exec Command="&quot;$(SolutionDir)packages\ILMerge.3.0.29\tools\net452\ILMerge.exe&quot; /internalize:&quot;$(MSBuildProjectPath)ilmerge.exclude&quot; /ndebug  /out:@(MainAssembly)  &quot;@(IntermediateAssembly)&quot; @(AssembliesToMerge->'&quot;%(FullPath)&quot;', ' ')" />
  <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>

笔记:

  1. $(SolutionDir)packages\ILMerge.3.0.29\tools\net452\ILMerge.exe您拥有的任何路径替换ILMerge.exe
  2. 您可以删除 Condition目标中的,使其也可以在Debug上合并,但随后Debugger可能无法正常工作
  3. 如果您不排除任何内容,则可以删除: /internalize:&quot;$(MSBuildProjectPath)ilmerge.exclude&quot;

0

看看乔莫的这篇文章。他有一个快速的过程可以将ILMerge入侵到msbuild系统中


1
hanselman.com/blog/…上的文章“在Visual Studio中的单一程序集中混合语言与ILMerge和MSBuild无缝结合”基于他的博客,并且通过在项目文件中设置ILMerge = True / False来增强了选择性地进行合并的技术。 。文章比Jomo的博客条目更为详细。
2010年
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.