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

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

我可以从命令行使用ILMerge完成此操作,但是我想将参考程序集和项目的合并集成到Visual Studio项目中。 从我的阅读中,我明白我可以通过MSBuild任务或目标来完成此任务,并将其添加到C#/ VB.NET项目文件中,但是由于MSBuild是一个大型主题,所以没有具体的例子。 此外,我发现一些引用将ILMerge命令添加到Post-build事件中。

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

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

  3. 使用Post-build事件会更好吗?

“ MSBuild ILMerge任务 ”(或MSBuild.ILMerge.Task )NuGet包使得这个过程非常简单。 它默认将任何“复制本地”引用合并到您的主要程序集。

注意:虽然这些软件包有相似的名字,但是这个和ILMerge.MSBuild.Tasks有所不同,Davide Icardi在他的回答中提到过。 我在这里build议的那个是在2014年8月首次发表的。

有些更多的信息可能对实施Scott Hanselman解决scheme的某些人有用。

当我第一次设置它时,会抱怨无法parsing对System.Core等的引用。这与.NET 4支持有关。 包含指向.NET 4 Framework目录的/ lib参数可以修复它(实际上只包含$(MSBuildBinPath))。

/lib:$(MSBuildBinPath)

然后我发现IlMerge会在合并时挂起。 它使用了一些CPU和大量的RAM,但是没有输出任何东西。 当然,我发现在stackoverflow的修复。

/targetplatform:v4

我还发现,Scott的博客文章中使用的一些MSBuild属性依赖于从项目目录执行MsBuild,所以我调整了一下它们。

然后,我将目标和ilmerge.exe移动到我们的源代码树的工具文件夹,这需要对path进行另一个小的调整。

我最终以下面的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参数。

这里有一个替代scheme:

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

PM> Install-Package 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)像往常一样build立你的项目。

文章在Visual Studio中使用ILMerge和MSBuild无缝地在Visual Studio中混合语言 http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx演示了如何在Visual Studio项目中使用ILMerge和MSBuild。

我在文章中find了一个问题: http : //www.hanselman.com/blog/MixingLanguagesInASAsAsmblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx 。

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

要解决这个问题 – 而不是:

 <Target Name="_CopyFilesMarkedCopyLocal"/> 

将这个条目添加到目标文件,而不是(仅适用于.NET 3.5)(过滤掉非ilmerge copylocal文件,并将其视为正常)

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

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

看看Jomo的这篇文章。 他有一个快速的过程来将ILMerge攻击到msbuild系统中

我的2美分 – 我拿起@贾森的回应,并使其工作我的解决scheme,我想在bin / Debug文件夹中生成与所有* .dlls在同一文件夹内的* .exe。

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

注意:这个解决scheme显然是硬编码到ILMerge nuget包版本中的。 请让我知道,如果你有一些改善build议。