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

时间:2010-03-31 19:56:10

标签: visual-studio visual-studio-2008 msbuild ilmerge

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

我可以从命令行使用ILMerge执行此操作,但我想将引用程序集和项目的这种合并集成到Visual Studio项目中。从我的阅读中,我了解到我可以通过MSBuild Task或Target执行此操作,只需将其添加到C#/ VB.NET项目文件中,但我找不到具体的示例,因为MSBuild是一个很大的主题。此外,我发现一些引用将ILMerge命令添加到Post-build事件。

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

  2. 这如何与可能的ILMerge.Targets文件相关联?

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

9 个答案:

答案 0 :(得分:52)

" MSBuild ILMerge task" (或MSBuild.ILMerge.Task)NuGet包使这个过程非常简单。它默认合并任何"复制本地"引用到主程序集中。

注意:虽然这些软件包的名称相似,但这个名称与Davide Icardi在answer中提到的ILMerge.MSBuild.Tasks不同。我在这里提出的建议于2014年8月首次发布。

答案 1 :(得分:18)

可能对某些实施Scott Hanselman's solution的人有用的更多信息。

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

/lib:$(MSBuildBinPath)

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

/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;', ' ')" /> 

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

答案 2 :(得分:18)

这是另一种解决方案:

1)从nuget

安装ILMerge.MSBuild.Tasks包
  

PM&GT;安装包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)照常构建项目。

答案 3 :(得分:15)

文章在Visual Studio中将单个程序集中的语言与http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx中的ILMerge和MSBuild 无缝混合,演示了如何在Visual Studio项目中使用ILMerge和MSBuild。

答案 4 :(得分:8)

我在文章http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.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>

答案 5 :(得分:4)

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

答案 6 :(得分: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包版本中。如果您有一些改进建议,请告诉我。

答案 7 :(得分: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上合并,但是调试器可能无法工作
  3. 如果您不排除任何内容,则可以删除:/internalize:&quot;$(MSBuildProjectPath)ilmerge.exclude&quot;

答案 8 :(得分:0)

查看Jomo的这篇文章。他有一个快速的过程来破解ILMerge进入msbuild系统