首页 文章

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

提问于
浏览
66

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

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

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

  • 这与可能的ILMerge.Targets文件有什么关系?

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

8 回答

  • 52

    MSBuild ILMerge task”(或 MSBuild.ILMerge.Task )NuGet包使这个过程非常简单 . 它默认将任何"copy local"引用合并到主程序集中 .

    Note: 尽管这些包具有相似的名称,但这个名称与Davide Icardi在他的_1428796中提到的 ILMerge.MSBuild.Tasks 不同 . 我在这里建议的那个首次发布于2014年8月 .

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

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

  • 1

    这是另一种解决方案:

    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)像往常一样构建项目 .

  • 15

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

  • 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>
    
  • 17

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

  • 0

    我的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包版本中 . 如果您有一些改进建议,请告诉我 .

  • 4

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

相关问题