использование ILMerge с библиотеками .NET 4 - PullRequest
51 голосов
/ 03 июня 2010

Две проблемы:

1) Базовая сборка .NET, не включенная в сборку ILMerged

У меня возникают проблемы с использованием ILMerge в моем пост-билде после обновления с .NET 3.5 / Visual Studio 2008 до .NET 4 / Visual Studio 2010. У меня есть решение с несколькими проектами, целевая структура которых установлена ​​на ".NET Рамки 4 ". Я использую следующую команду ILMerge для объединения отдельных библиотек проекта в одну библиотеку:

if not $(ConfigurationName) == Debug
  if exist "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
    "C:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe"
      /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
      /lib:"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
      /keyfile:"$(SolutionDir)$(SolutionName).snk"
      /targetplatform:v4
      /out:"$(SolutionDir)bin\development\$(SolutionName).dll"
      "$(SolutionDir)Connection\$(OutDir)Connection.dll"
      ...other project DLLs...
      /xmldocs 

Если я не укажу указание расположения каталога платформы .NET 4, я получу сообщение об ошибке «Неразрешенная ссылка на сборку не разрешена: система» от ILMerge. Если я остановлюсь, указав расположение каталога MSTest, я получу сообщение об ошибке «Неразрешенная ссылка на сборку не разрешена: Microsoft.VisualStudio.QualityTools.UnitTestFramework».

Команда ILMerge, приведенная выше, работает и создает DLL. Однако, когда я ссылаюсь на эту DLL в другом проекте .NET 4 C # и пытаюсь использовать код внутри нее, я получаю следующее предупреждение:

Первичная ссылка «MyILMergedDLL» не может быть разрешена, поскольку она имеет косвенную зависимость от сборки .NET Framework «mscorlib, Version = 4.0, Culture = нейтральный, PublicKeyToken = b77a5c561934e089», версия которого выше «4.0.65535.65535» чем версия "4.0.0.0" в текущей целевой структуре.

Если я затем удаляю флаг /targetplatform:v4 и пытаюсь использовать MyILMergedDLL.dll, я получаю следующую ошибку:

Тип 'System.Xml.Serialization.IXmlSerializable' определен в сборке, на которую нет ссылок. Необходимо добавить ссылку на сборку 'System.Xml, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089'.

Не похоже, что мне нужно это делать. Тот, кто использует мой API MyILMergedDLL.dll, не должен добавлять ссылки на библиотеки, на которые он ссылается. Как я могу обойти это?

2) TypeLoadException Только при использовании объединенной сборки

Редактировать: сверх этого, даже если я добавлю ссылку на System.Xml в потребительском проекте, который использует MyILMergedDLL.dll, использование некоторого кода в MyILMergedDLL.dll дает это исключение:

System.TypeLoadException: не удалось загрузить тип 'System.Func`2' из сборки 'MyILMergedDLL, версия = 1.0.1.1, культура = нейтральная, PublicKeyToken = ...'.

Это код в моем потребительском проекте; строка, которая вызвала TypeLoadException, является второй:

var keys = new[] {"a", "b", "c"};
var row = new Row(keys);

Конкретный конструктор Row, который выбрасывает TypeLoadException, определен в общедоступном классе в MyILMergedDLL, и когда я использую этот конструктор при обращении к отдельным библиотекам проекта, он работает нормально. Исключение составляет только когда я использую этот конструктор при обращении к слитой в DLL библиотеке. Я не знаю, что происходит.

Вот этот конструктор:

public Row(IEnumerable<string> keys) : base(keys) { }

И base, на который он ссылается, имеет следующий код:

foreach (string key in keys.Where(
    key => !string.IsNullOrEmpty(key)
))
{
    _dic.Add(key, string.Empty);
}

Ответы [ 6 ]

48 голосов
/ 03 июня 2010

Был выпущен самый последний релиз для решения проблем с x64. Свяжитесь с Майком Барнеттом напрямую, если у вас все еще есть проблемы (mbarnett в microsoft dot com)


Добавление. Есть что-то очень, очень неправильное в вашей опции /lib:"C:\Windows\Microsoft.NET\Framework64\v4.0.30319". В последнее время после выпуска .NET 4.5 возникали проблемы с программистами. Это каталог , а не , подходящий для справочных сборок .NET 4.0. Его содержимое перезаписывается сборками 4.5, вы больше не можете использовать его для установки .NET 4.0. Полученная ошибка во время выполнения очень неловкая, программа больше не может найти определенные типы. Обычно бомбардировка по атрибуту [Extension], иногда по интерфейсу ICommand.

Эти и некоторые другие типы были перемещены из одной сборки в другую. Использование правильных эталонных сборок является жестким требованием. Вы должны использовать:

 /lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"

Настройте в соответствии с вашей конкретной машиной и целевой версией фреймворка.

21 голосов
/ 23 марта 2011

Вот «Строка посткомпоновки» для Visual Studio 2010 SP1 с использованием .NET 4.0. Я создаю консоль .exe со всеми вложенными файлами .dll, включенными в него.

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

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

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

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

Если у вас проблемы с тем, что он не работает, добавьте «echo» перед командой «Post Build». Затем откройте окно «Вывод» в Visual Studio (View..Output) и проверьте точную команду, сгенерированную Visual Studio. В моем конкретном случае точная команда была:

"T:\PhiEngine\CSharp\ILMerge\ILMerge.exe" /out:"T:\PhiEngine\CSharp\Server Side\deploy\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\NfServiceDataHod.History.exe" "T:\PhiEngine\CSharp\Server Side\NfServiceDataHod\bin\Debug\*.dll" /target:exe /targetplatform:v4,C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /wildcards

Обновление

Добавил это в мой шаг «Постстройка», он заменяет все .exe + .dll файлы одним объединенным .exe. Он также сохраняет файл отладки .pdb без изменений:

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 name we started with.
ren "$(TargetDir)$(TargetName).all.pdb" "$(TargetName).pdb"
ren "$(TargetDir)$(TargetName).all.exe" "$(TargetName).exe"
exit 0
2 голосов
/ 26 февраля 2012

Вы также можете добавить файл конфигурации со следующим:

<?xml version ="1.0"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
  </startup>
</configuration>

Взято с здесь

2 голосов
/ 23 марта 2011

Другие альтернативы:

1 голос
/ 26 апреля 2013

Просто установите для ссылок PresentationCore и PresentationFramework значение «Copy Local = True» в окне свойств Visual Studio (после выбора ссылок в обозревателе решений). Это решит проблему без жесткого кодирования пути фреймворка. Я предпочитаю это решение, потому что путь отличается в зависимости от того, является ли сервер разработчика / сборки 64-битным или 32-битным и неизбежно изменится по мере выпуска новых версий .NET / VS.

0 голосов
/ 12 июня 2018

Для тех, кто использует ILMerge из задач сообщества в .csproj:

<ILMerge InputAssemblies="@(MergeAssemblies)"
         ...
         TargetPlatformVersion="v4"
         TargetPlatformDirectory="$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
/>

У нас смешанный парк агентов сборки CI, поэтому мы используем переменную среды $ (ProgramFiles) для указания правильного пути (папка drive + x86 / x64), как это было рекомендовано MSBuild Team .

...