Лучшие практики ILMerge

Вы используете ILMerge? Вы используете ILMerge для объединения нескольких сборок, чтобы упростить развертывание DLL? Обнаружили ли вы проблемы с развертыванием / управлением версиями в производственной среде после объединения сборок ILMerging?

Мне нужен совет относительно использования ILMerge для уменьшения трения при развертывании, если это вообще возможно.

Ответов (12)

Решение

Я использую ILMerge почти для всех своих приложений. Я интегрировал его прямо в процесс сборки релиза, так что в итоге я получаю по одному exe на приложение без дополнительных dll.

Вы не можете использовать ILMerge для любых сборок C++, которые имеют собственный код. Вы также не можете использовать ILMerge для каких-либо сборок, содержащих XAML для WPF (по крайней мере, я не добился успеха с этим). Он жалуется во время выполнения, что ресурсы не могут быть обнаружены.

Я написал исполняемый файл оболочки для ILMerge, в котором я передаю имя запускаемого exe для проекта, который хочу объединить, и имя выходного exe, а затем оно отражает зависимые сборки и вызывает ILMerge с соответствующими параметрами командной строки. Теперь, когда я добавляю в проект новые сборки, это намного проще, мне не нужно помнить об обновлении скрипта сборки.

Мы только начали использовать ILMerge в наших решениях, которые распространяются и используются в других наших проектах, и пока все идет хорошо. Вроде все нормально работает. Мы даже запутали упакованную сборку напрямую.

Мы планируем сделать то же самое со сборками MS Enterprise Library.

Единственная реальная проблема, с которой я сталкиваюсь, - это управление версиями отдельных сборок из пакета.

Мы столкнулись с проблемами при объединении библиотек DLL, ресурсы которых находятся в одном пространстве имен. В процессе слияния одно из пространств имен ресурсов было переименовано, и поэтому ресурсы не удалось найти. Может, мы просто что-то делаем не так, но все еще изучаем проблему.

Вступление

В этом посте показано, как заменить все .exe + .dll files одним combined .exe . Он также сохраняет .pdb нетронутым файл отладки .

Для консольных приложений

Вот базовая Post Build String версия Visual Studio 2010 SP1 с использованием .NET 4.0. Я создаю консоль .exe со всеми вложенными в нее файлами .dll.

"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

Основные подсказки

  • На выходе получается файл " AssemblyName.all.exe", который объединяет все вложенные библиотеки в один .exe.
  • Обратите внимание на ILMerge\каталог. Вам нужно либо скопировать утилиту ILMerge в каталог решения (чтобы вы могли распространять исходный код, не беспокоясь о документировании установки ILMerge), либо изменить этот путь, чтобы он указывал на то, где находится ILMerge.exe.

Дополнительные подсказки

Если у вас проблемы с тем, что он не работает, включите Output и выберите Show output from: Build . Проверьте точную команду, фактически созданную Visual Studio, и проверьте наличие ошибок.

Пример сценария сборки

Этот скрипт заменяет все .exe + .dll files одним combined .exe . Он также сохраняет нетронутым отладочный файл .pdb.

Чтобы использовать, вставьте это в свой Post Build шаг под Build Events вкладкой в ​​проекте C# и убедитесь, что вы настроили путь в первой строке, чтобы он указывал на ILMerge.exe :

rem Create a single .exe that combines the root .exe and all subassemblies.
"$(SolutionDir)ILMerge\ILMerge.exe" /out:"$(TargetDir)$(TargetName).all.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards
rem Remove all subassemblies.
del *.dll
rem Remove all .pdb files (except the new, combined pdb we just created).
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).all.pdb.temp"
del *.pdb
ren "$(TargetDir)$(TargetName).all.pdb.temp" "$(TargetName).all.pdb"
rem Delete the original, non-combined .exe.
del "$(TargetDir)$(TargetName).exe"
rem Rename the combined .exe and .pdb to the original project name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0

Я знаю, что это старый вопрос, но мы не только используем ILMerge для уменьшения количества зависимостей, но и для интернализации «внутренних» зависимостей (например, automapper, restsharp и т. Д.), Которые используются утилитой. Это означает, что они полностью абстрагированы, и проекту, использующему объединенную утилиту, не нужно о них знать. Это снова уменьшает количество необходимых ссылок в проекте и позволяет ему использовать / обновлять собственную версию той же внешней библиотеки, если это необходимо.

У нас была такая же проблема с объединением зависимостей WPF ... Кажется, что ILMerge не справляется с этим. Costura.Fody, однако, отлично сработал для нас и заняло около 5 минут, чтобы начать ... очень хороший опыт.

Просто установите с помощью Nuget (выбрав правильный проект по умолчанию в консоли диспетчера пакетов). Он вводится в целевой проект, и настройки по умолчанию сразу сработали для нас.

Он объединяет все библиотеки DLL, помеченные "Copy Local" = true, и создает объединенный .EXE (вместе со стандартным выводом), который хорошо сжат по размеру (намного меньше, чем общий размер вывода).

Лицензия MIT, поэтому вы можете изменять / распространять по мере необходимости.

https://github.com/Fody/Costura/

Обратите внимание, что для программ с графическим интерфейсом пользователя Windows (например, WinForms) вы захотите использовать переключатель / target: winexe .
Параметр / target: exe создает объединенное консольное приложение.

Я только начинаю использовать ILMerge как часть моей сборки CI, чтобы объединить множество мелкозернистых контрактов WCF в единую библиотеку. Он работает очень хорошо, однако новая объединенная библиотека не может легко сосуществовать с ее библиотеками компонентов или другими библиотеками, которые зависят от этих библиотек компонентов.

Если в новом проекте вы ссылаетесь как на свою библиотеку ILMerged, так и на устаревшую библиотеку, которая зависит от одного из входных данных, которые вы передали в ILMerge, вы обнаружите, что не можете передать какой-либо тип из библиотеки ILMerged ни одному методу в устаревшая библиотека без какого-либо сопоставления типов (например, автоматического или ручного сопоставления). Это связано с тем, что после того, как все скомпилировано, типы эффективно квалифицируются именем сборки.

Имена также будут конфликтовать, но вы можете исправить это с помощью внешнего псевдонима .

Я бы посоветовал избегать включения в вашу объединенную сборку любой общедоступной библиотеки, которую предоставляет ваша объединенная сборка (например, через тип возвращаемого значения, параметр метода / конструктора, поле, свойство, общий ...), если вы не знаете наверняка, что пользователь ваша объединенная сборка не зависит и никогда не будет зависеть от отдельно стоящей версии той же библиотеки.

Мы используем ILMerge во многих проектах. Web Service Software Factory , например , производит что - то вроде 8 сборок , как его выход. Мы объединяем все эти библиотеки DLL в одну, чтобы хост службы мог ссылаться только на одну DLL.

Это несколько облегчает жизнь, но и в этом нет ничего страшного.

Мы используем ILMerge в блоках приложений Microsoft - вместо 12 отдельных файлов DLL у нас есть один файл, который мы можем загрузить в наши клиентские области, плюс структура файловой системы намного лучше.

После объединения файлов мне пришлось отредактировать список проектов Visual Studio, удалить 12 отдельных сборок и добавить один файл в качестве ссылки, иначе он пожаловался бы, что не может найти конкретную сборку. Я не слишком уверен, как это будет работать при пост-развертывании, возможно, стоит попробовать.

Недавно у меня возникла проблема, когда я включил сборку в сборку, у меня были некоторые классы, которые вызывались через отражение в CMS с открытым исходным кодом Umbraco.

Информация для выполнения вызова через отражение была взята из таблицы db, которая имела имя сборки и пространство имен реализованного класса и интерфейса. Проблема заключалась в том, что вызов отражения завершался ошибкой при слиянии dll, однако, если dll была отдельной, все работало нормально. Я думаю, проблема может быть похожа на ту, что у longeasy?

Мне кажется, что лучшая практика №1 ILMerge - не использовать ILMerge. Вместо этого используйте SmartAssembly . Одна из причин этого заключается в том, что лучший метод №2 ILMerge - всегда запускать PEVerify после выполнения ILMerge, потому что ILMerge не гарантирует, что он правильно объединит сборки в допустимый исполняемый файл.

Другие недостатки ILMerge:

  • при слиянии он удаляет комментарии XML (если бы меня это волновало, я бы использовал инструмент обфускации)
  • он неправильно обрабатывает создание соответствующего файла .pdb

Еще один инструмент, на который стоит обратить внимание, - это Mono.Cecil и Mono.Linker [2].

[2]: http: // www.mono-project.com/Linker