Як інтегрувати ILMerge у процес побудови Visual Studio для об’єднання збірок?


77

Я хочу об’єднати одну збірку .NET DLL та один проект бібліотеки класів C #, на який посилається проект консольної програми VB.NET, в один виконуваний файл консолі командного рядка.

Я можу зробити це за допомогою ILMerge з командного рядка, але я хочу інтегрувати це об'єднання посилальних збірок та проектів у проект Visual Studio. З мого прочитання я зрозумів, що можу зробити це за допомогою завдання MSBuild або цілі і просто додати його до файлу проекту C # / VB.NET, але конкретного прикладу я не можу знайти, оскільки MSBuild - це велика тема. Більше того, я знаходжу деякі посилання, які додають команду ILMerge до події Post-build.

  1. Як інтегрувати ILMerge у проект Visual Studio (C # / VB.NET), який є лише проектами MSBuild, щоб об’єднати всі збірки, на які посилаються (copy-local = true), в одну збірку?

  2. Як це пов’язано з можливим файлом ILMerge.Targets?

  3. Чи краще використовувати подію Post-build?


Ви також можете використовувати "Рядок побудови повідомлення", щоб зробити це, як згадано [Тут] [1] [1]: stackoverflow.com/questions/2961357/…
Заін Алі,

Відповіді:


65

Пакет " Завдання MSBuild ILMerge " (або MSBuild.ILMerge.Task) NuGet робить цей процес досить простим. За замовчуванням об’єднання будь-яких посилань "копіювати локальні" в основну збірку.

Примітка: Хоча пакунки мають схожі назви, цей відрізняється від того, ILMerge.MSBuild.Tasksщо Давіде Ікарді згадав у своїй відповіді . Той, який я пропоную тут, був вперше опублікований у серпні 2014 року.


3
Рішення як слід! +1
Рей

1
Це має бути прийнятим рішенням. Робить це дійсно безболісно. Дякую!
Алек Девіс,

Гарний: D Не ідеально, оскільки він "забув" включити додаткові файли в каталог виводу, але все ще добре ^^
Етеніл

1
Працює дуже приємно: включіть пакет, побудуйте, і все готово! Це ввімкнено з піктограмою.
Ремко

1
Я не можу знайти жодної документації для MSBuild ILMerge, як я нею користуюся? Хтось має приклад чи інструкцію?
MrDysprosium

19

Ось альтернативне рішення:

1) Встановіть пакет ILMerge.MSBuild.Tasks з nuget

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) Побудуйте свій проект, як зазвичай.


Це справді яма, цей пакет не підтримується краще. Я використовував його, але йому не вистачає можливості встановити TargetPlatform, що є важливим для .NET 4.5 / .NET 4.0 compat.
Eoin Campbell

@davidlcardi, як замінити ім'я цільового файлу, dll_to_merge тощо
Сміт,

@Smith TargetFileName вже є змінною msbuild, тому вам не потрібно її замінювати. LIB1_To_Merge.dll - це фіксовані імена. Можливо, за допомогою деяких більш складних скриптів msbuild ви можете знайти всі збірки, на які посилаються, але я не знаю, як це зробити.
Давіде Ікарді

@DavideIcardi pls привіт, подивіться, чи можете ви відповісти на це stackoverflow.com/questions/15588086/…
Сміт,

1
Чи є спосіб також зробити цей знак моїм збором, використовуючи мій файл ключа?
Стівен Лемменс

18

Дещо більше інформації, яка може бути корисною для деяких людей, що впроваджують рішення Скотта Хензельмана .

Коли я вперше це налаштовував, він скаржився на те, що не може вирішити посилання на System.Core тощо. Це щось спільне з підтримкою .NET 4. Включення аргументу / lib, що вказує на каталог .NET 4 Framework, це виправляє (насправді просто включіть $ (MSBuildBinPath)).

/lib:$(MSBuildBinPath)

Потім я виявив, що IlMerge зависне під час злиття. Він використовував трохи процесора і багато оперативної пам'яті, але нічого не видавав. Звичайно, я знайшов виправлення для stackoverflow .

/targetplatform:v4

Я також виявив, що деякі властивості MSBuild, використані у статті блогу Скотта, покладалися на виконання MsBuild з каталогу проекту, тому я трохи їх підправив.

Потім я перемістив цілі & ilmerge.exe до папки інструментів нашого вихідного дерева, що вимагало ще одного невеликого налаштування шляхів ...

Врешті-решт, я отримав наступний елемент Exec, який замінив елемент у оригінальній статті Скотта:

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

ОНОВЛЕННЯ Я також знайшов відповідь Logic Labs щодо збереження поведінки CopyLocal та просто виключення збірки ilMerged з CopyLocal, якщо ви використовуєте пакети Nuget. В іншому випадку вам потрібно вказати аргумент / lib для кожного каталогу пакунків згаданих збірок, які не об'єднуються.


Насправді я закінчив із завантаженням ILMerge.exe, додавши його до керування джерелами та записавши якусь команду в Події після збірки
Haobo,

15

Стаття Змішування мов в одній збірці у Visual Studio без проблем з ILMerge та MSBuild за адресою http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx демонструє, як використовувати ILMerge та MSBuild у Visual Studio Studio.


1
З цим кодом виникла проблема, якщо ви не хочете ILMerge усі свої посилання. Подивіться мою відповідь
Logic Labs

9

Одне питання, яке я знайшов у статті за адресою: http://www.hanselman.com/blog/MixingLanguagesInASingleAssemblyInVisualStudioSeamlesslyWithILMergeAndMSBuild.aspx .

Якщо у вас є посилання, які ви не бажаєте ILMerge, тоді код у статті зазнає помилки, оскільки він замінює поведінку CopyLocal за замовчуванням, щоб нічого не робити.

Щоб це виправити - Замість:

<Target Name="_CopyFilesMarkedCopyLocal"/> 

Натомість додайте цей запис до цільового файлу (лише .NET 3.5) (щоб відфільтрувати файли, що не залежать від копіювання, і поводитися з ними як із звичайними)

<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
Легко пропустити його оновлений та детальний запис у блозі, тому я буду посилатися на нього тут, тлумачення.консультації.net/blogs/kzu/archive/2009/02/23/… .
AMissico

Стаття, на яку я посилався, є нещодавнішою, але менш детальною, вона має кілька цікавих коментарів.
Рохан Вест

@WernerCD Відредагував відповідь, надавши фіксоване посилання через Інтернет-архів. І ось другий .
takrl

1

Мої 2 центи - я підібрав відповідь @ Jason і змусив її працювати для мого рішення, де я хотів створити * .exe у папці bin / Debug з усіма * .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в цілі, щоб також об'єднати на Налагодження, але тоді налагоджувач може не працювати
  3. Якщо ви не виключаєте нічого, ви можете видалити: /internalize:&quot;$(MSBuildProjectPath)ilmerge.exclude&quot;

0

Перегляньте цю статтю Джомо. У нього є швидкий процес злому ILMerge в систему msbuild


1
Стаття Змішування мов в одній збірці у Visual Studio без проблем з ILMerge та MSBuild за адресою hanselman.com/blog/… заснована на його блозі та вдосконалює техніку, яка дозволяє вибірково об’єднувати, встановлюючи ILMerge = True / False у файлі проекту . Стаття набагато детальніша, ніж запис у блозі Джомо.
AMissico
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.