Wie integriere ich ILMerge in den Visual Studio-Erstellungsprozess, um Assemblies zusammenzuführen?

77

Ich möchte eine .NET DLL-Assembly und ein C # -Klassenbibliotheksprojekt, auf das von einem VB.NET Console Application-Projekt verwiesen wird, in einer ausführbaren Befehlszeilenkonsole zusammenführen.

Ich kann dies mit ILMerge über die Befehlszeile tun, möchte diese Zusammenführung von Referenzassemblys und -projekten jedoch in das Visual Studio-Projekt integrieren. Aus meiner Lektüre geht hervor, dass ich dies über eine MSBuild-Aufgabe oder ein Ziel tun und es einfach einer C # / VB.NET-Projektdatei hinzufügen kann, aber ich kann kein spezifisches Beispiel finden, da MSBuild ein großes Thema ist. Außerdem finde ich einige Referenzen, die den ILMerge-Befehl zum Post-Build-Ereignis hinzufügen.

  1. Wie integriere ich ILMerge in ein Visual Studio-Projekt (C # / VB.NET), bei dem es sich nur um MSBuild-Projekte handelt, um alle referenzierten Assemblys (copy-local = true) in einer Assembly zusammenzuführen?

  2. Wie knüpft dies an eine mögliche ILMerge.Targets-Datei an?

  3. Ist es besser, das Post-Build-Ereignis zu verwenden?

AMissico
quelle
Sie können auch "Post Build String" verwenden, um dies zu tun, wie erwähnt [Hier] [1] [1]: stackoverflow.com/questions/2961357/…
Zain Ali

Antworten:

65

Das NuGet-Paket " MSBuild ILMerge task " (oder MSBuild.ILMerge.Task) macht diesen Vorgang recht einfach. Standardmäßig werden alle "lokalen" Referenzen in Ihre Hauptbaugruppe kopiert.

Hinweis: Obwohl die Pakete ähnliche Namen haben, unterscheidet sich dieses von ILMerge.MSBuild.Tasksdem in seiner Antwort erwähnten Davide Icardi . Die hier vorgeschlagene wurde erstmals im August 2014 veröffentlicht.

Ganzheitlicher Entwickler
quelle
3
Eine Lösung wie sie sein sollte! +1
Ray
1
Dies sollte die akzeptierte Lösung sein. Macht es wirklich schmerzlos. Vielen Dank!
Alek Davis
Schön: D Nicht perfekt, da es "vergessen" hat, zusätzliche Dateien in das Ausgabeverzeichnis aufzunehmen, aber immer noch gut ^^
Ethenyl
1
Funktioniert sehr gut: Paket einbinden, bauen und fertig! Es ist das Ein mit einem Symbol.
Remco
1
Ich kann keine Dokumentation für MSBuild ILMerge finden. Wie verwende ich sie? Hat jemand ein Beispiel oder eine Anleitung?
MrDysprosium
19

Hier eine alternative Lösung:

1) Installieren Sie das ILMerge.MSBuild.Tasks-Paket von Nuget

PM> Install-Package ILMerge.MSBuild.Tasks

2) Bearbeiten Sie die * .csproj-Datei des Projekts, das Sie zusammenführen möchten, indem Sie den folgenden Code hinzufügen:

  <!-- 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) Erstellen Sie Ihr Projekt wie gewohnt.

Davide Icardi
quelle
Es ist eine echte Grube, dass dieses Paket nicht besser gepflegt wird. Ich habe es verwendet, aber es fehlt die Möglichkeit, TargetPlatform festzulegen, was für die .NET 4.5 / .NET 4.0-Kompatibilität von Bedeutung ist.
Eoin Campbell
@ Davidlcardi, wie ich den Zieldateinamen, dll_to_merge usw. ersetzen
Smith
@Smith TargetFileName ist bereits eine msbuild-Variable, sodass Sie sie nicht ersetzen müssen. Die LIB1_To_Merge.dll sind feste Namen. Wahrscheinlich können Sie mit einigen komplexeren msbuild-Skripten alle referenzierten Assemblys finden, aber ich weiß nicht, wie es geht.
Davide Icardi
@ DavidIcardi Bitte helfen Sie mir zu sehen, ob Sie auf diese stackoverflow.com/questions/15588086/…
Smith
1
Gibt es eine Möglichkeit, dieses Zeichen auch mithilfe meiner Schlüsseldatei zu meiner Baugruppe zu machen?
Steven Lemmens
18

Einige weitere Informationen, die für einige Leute, die die Lösung von Scott Hanselman implementieren, nützlich sein könnten .

Als ich dies zum ersten Mal einrichtete, beschwerte es sich darüber, dass Verweise auf System.Core usw. nicht aufgelöst werden konnten. Dies hat etwas mit der Unterstützung von .NET 4 zu tun. Das Einfügen eines / lib-Arguments, das auf das .NET 4 Framework-Verzeichnis verweist, behebt es (in der Tat nur das $ (MSBuildBinPath)).

/lib:$(MSBuildBinPath)

Ich fand dann heraus, dass IlMerge beim Zusammenführen hängen bleiben würde. Es verbrauchte ein bisschen CPU und viel RAM, gab aber nichts aus. Ich habe das Update für den Stackoverflow natürlich gefunden .

/targetplatform:v4

Ich fand auch heraus, dass einige der MSBuild-Eigenschaften, die in Scotts Blog-Artikel verwendet wurden, auf der Ausführung von MsBuild aus dem Projektverzeichnis beruhten, also habe ich sie ein wenig optimiert.

Ich habe dann die Ziele & ilmerge.exe in den Tools-Ordner unseres Quellbaums verschoben, was eine weitere kleine Änderung an den Pfaden erforderlich machte ...

Am Ende hatte ich schließlich das folgende Exec- Element, um das in Scotts Originalartikel zu ersetzen:

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

UPDATE Ich fand auch die Antwort von Logic Labs , das CopyLocal-Verhalten beizubehalten und nur ilMerged-Assemblys von CopyLocal auszuschließen, wenn Sie Nuget-Pakete verwenden. Andernfalls müssen Sie für jedes Paketverzeichnis der referenzierten Assemblys, die nicht zusammengeführt werden, ein / lib-Argument angeben.

Jason Duffett
quelle
Tatsächlich habe ich die Datei ILMerge.exe heruntergeladen, zur Quellcodeverwaltung hinzugefügt und einen Befehl in Post-Build Event
Haobo
9

Ein Problem, das ich mit dem Artikel gefunden habe: http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamhlessWithILMergeAndMSBuild.aspx .

Wenn Sie Verweise haben, die Sie nicht auf ILMerge übertragen möchten, schlägt der Code im Artikel fehl, da er das Standardverhalten von CopyLocal überschreibt, um nichts zu tun.

Um dies zu beheben - Anstelle von:

<Target Name="_CopyFilesMarkedCopyLocal"/> 

Fügen Sie diesen Eintrag stattdessen zur Zieldatei hinzu (nur .NET 3.5) (um die nicht ilmerge kopylokalen Dateien herauszufiltern und wie gewohnt zu behandeln).

<Target Name="AfterResolveReferences">
    <Message Text="Filtering out ilmerge assemblies from ReferenceCopyLocalPaths" Importance="High" />
    <ItemGroup>
        <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.IlMerge)'=='true'" />
    </ItemGroup>
</Target>
Logic Labs
quelle
1
Oh ja! Dies ist ENDGÜLTIG erforderlich, wenn Sie Nuget verwenden. Andernfalls müssen Sie den Paketinhaltsordner jeder Assembly angeben, auf die Sie nicht zusammenführen. Vielen Dank!
Jason Duffett
4

Dies ist ein großartiger Artikel , der Ihnen zeigt, wie Sie Ihre referenzierten Assemblys in die Ausgabe-Assembly zusammenführen. Es zeigt genau, wie Assemblys mit msbuild zusammengeführt werden.

Rohan West
quelle
1
Sein aktualisierter und detaillierterer Blogeintrag ist leicht zu übersehen, daher werde ich hier auf clariusconsulting.net/blogs/kzu/archive/2009/02/23/… verweisen .
AMissico
Der Artikel, auf den ich verwiesen habe, ist neuer, aber weniger detailliert. Er enthält einige interessante Kommentare.
Rohan West
@WernerCD Die Antwort wurde bearbeitet, um einen festen Link über das Internetarchiv bereitzustellen. Und hier ist der zweite .
Takrl
1

Meine 2 Cent - Ich habe @ Jasons Antwort aufgegriffen und sie für meine Lösung zum Laufen gebracht, bei der ich die * .exe im Ordner bin / Debug mit allen * .dlls im selben Ordner generieren wollte.

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

Hinweis: Diese Lösung ist offensichtlich in der ILMerge Nuget-Paketversion fest codiert. Bitte lassen Sie mich wissen, wenn Sie Verbesserungsvorschläge haben.

rui
quelle
1

Bearbeiten Sie die * .csproj-Datei des Projekts, das Sie zusammenführen möchten, indem Sie den folgenden Code hinzufügen:

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

Anmerkungen:

  1. Ersetzen $(SolutionDir)packages\ILMerge.3.0.29\tools\net452\ILMerge.exeSie durch den Pfad, in dem Sie sich befinden ILMerge.exe.
  2. Sie können das Conditionim Ziel entfernen, um es auch beim Debuggen zusammenzuführen, aber dann funktioniert der Debugger möglicherweise nicht
  3. Wenn Sie nichts ausschließen, können Sie Folgendes entfernen: /internalize:&quot;$(MSBuildProjectPath)ilmerge.exclude&quot;
NT
quelle
0

Lesen Sie diesen Artikel von Jomo. Er hat einen schnellen Prozess, um ILMerge in das msbuild-System zu hacken

JaredPar
quelle
1
Der Artikel Sprachen in einer einzelnen Assembly in Visual Studio nahtlos mit ILMerge und MSBuild unter hanselman.com/blog/… mischen basiert auf seinem Blog und erweitert die Technik, mit der Sie selektiv zusammenführen können, indem Sie ILMerge = True / False in der Projektdatei festlegen . Der Artikel ist viel detaillierter als Jomos Blogeintrag.
AMissico