Можно ли объединить только подмножество зависимостей с помощью ILMerge?

Я пытаюсь что-то исследовательское:

Скажем, у меня есть библиотека «coolproject», и у нее есть зависимости от one.dll, two.dll и three.dll.

Я хотел бы использовать ILMerge для объединения coolproject с one.dll и two.dll, но НЕ three.dll. По завершении слияния у меня должны быть coolproject.dll и three.dll. Везде, где я намереваюсь использовать coolproject.dll, я должен также ссылаться на three.dll

Это вообще возможно? Всякий раз, когда я пытаюсь это сделать, я получаю. Unresolved assembly reference not allowed: three. Я опускаю three.dll, устанавливая «Копировать локально» = false.

[ИЗМЕНИТЬ]:

Выполняется следующим образом:

ILMerge /targetplatform:v2 /log /internalize /out:bin\coolproject.dll obj\Debug\coolproject.dll C:\Users\Nick\Projects\test\bin\one.dll C:\Users\Nick\Projects\test\bin\two.dll

person NickSuperb    schedule 24.01.2013    source источник
comment
Как вы вызываете ILMerge? Сообщение об ошибке правильное IIRC, вам нужно three.dll там (или где-то еще, где ILMerge может его увидеть), но это не будет автоматически означать, что оно также объединено.   -  person    schedule 24.01.2013
comment
Это для проекта WPF?   -  person Bob.    schedule 24.01.2013
comment
@Bob это стандартная библиотека C#.   -  person NickSuperb    schedule 24.01.2013
comment
@hvd Я использую цель сборки. Однако я только что заметил эту статью. hanselman.com/blog/ Хотя это не совсем связано, он использует специальную цель для определить список сборок. Стоит попробовать.   -  person NickSuperb    schedule 24.01.2013
comment
Для целей вашего вопроса я вызываю ILMerge (аргументы), и я создал цель сборки, которая вызывает ILMerge (аргументы), что означает одно и то же: вам нужно показать аргументы. Это я и хотел спросить, извините, если неясно.   -  person    schedule 24.01.2013
comment
@hvd Добавлены аргументы в вопрос   -  person NickSuperb    schedule 25.01.2013
comment
Это меня удивляет. Я делаю что-то очень похожее, с несколькими DLL в одном каталоге, но объединяю только две из них, но это не требует особых усилий. Я проверю точную командную строку, которую использую, когда смогу.   -  person    schedule 25.01.2013
comment
Теперь я перепроверил, что ILMerge /targetplatform:v4 /internalize /out:O.dll A.dll B.dll работает для меня. A.dll ссылается на B.dll, C.dll и D.dll, все они находятся в одном каталоге. O.dll содержит методы A.dll и B.dll и требует C.dll и D.dll во время выполнения.   -  person    schedule 25.01.2013
comment
Я думаю, что ключ находится в одном каталоге. Это не так для меня. Смотрите мой ответ ниже.   -  person NickSuperb    schedule 07.02.2013


Ответы (3)


Причина, по которой это не работает, оказалась довольно простой: ILMerge должен иметь возможность найти dll, которую вы исключили из списка.

При оценке зависимостей в целевой библиотеке ILMerge по умолчанию проверяет различные местоположения, чтобы идентифицировать зависимую библиотеку (\bin, GAC и т. д.), даже если вы не указали ее в списке командной строки. Если он не может найти эту библиотеку, вы должны указать ее местоположение с помощью переключателя \lib. В противном случае вы увидите ошибку Unresolved assembly reference not allowed: three.

Пример:

ILMerge /lib:..\three\bin\three.dll /targetplatform:v2 /log /internalize /out:bin\coolproject.dll obj\Debug\coolproject.dll C:\Users\Nick\Projects\test\bin\one.dll C:\Users\Nick\Projects\test\bin\two.dll
person NickSuperb    schedule 06.02.2013
comment
Остается ли при этом файл three.dll в качестве внешней ссылки в объединенной библиотеке DLL или он также интернализует ее? Спасибо. - person Mightymuke; 07.02.2013
comment
Это приводит к тому, что three.dll является внешней ссылкой, что и было целью в данном случае. Это также может быть последним решением для ошибок конфликтов типов и пространств имен для внутренних сборок. - person NickSuperb; 07.02.2013
comment
Если я попытаюсь указать DLL в аргументе /lib:, ILMerge выйдет из строя, и указанный каталог поиска «C:\a\b\c.dll» не будет найден. - person Joshua Evensen; 09.01.2014
comment
Вам нужно будет использовать переменную проекта в файле сборки для правильной ссылки на каталог (кроме базового C:). Например: $(ProjectDir)..\a\b\c.dll - person Will; 16.02.2016
comment
кажется, вы можете использовать /lib только с каталогом? - person joe; 02.06.2021

Я написал небольшой инструмент, чтобы справиться с этим.

Исходный код можно найти на @ https://github.com/leppie/ReferenceRemover.

В вашем случае он будет использоваться как:

ReferenceRemover three.dll "(one|two).*" coolproject.dll

Объяснение аргументов:

  1. Сборка для проверки
  2. Регулярное выражение для соответствия ссылкам
  3. Сборка, на которую нужно перенаправить

Результатом является three.dll со скорректированными ссылками.

person leppie    schedule 25.01.2013

Я думаю, вы ищете параметр «исключить» для переключателя /internalize. Например, если вы используете

/internalize:excludes.txt

где файл excludes.txt содержит

three.dll

он усвоит one.dll и two.dll, но оставит three.dll в качестве внешней зависимости.

Вот пара постов в блоге, в которых подробно рассказывается:

Обновление: из документации:

2.10 Исключить файл

общедоступная строка ExcludeFile { получить; набор; }

Это свойство используется только в сочетании со свойством Internalize (раздел 2.12). Когда это установлено перед вызовом Merge, оно указывает путь и имя файла, которые будут использоваться для идентификации типов, видимость которых не должна изменяться. Если Internalize имеет значение true, а ExcludeFile — «», то все типы в любой сборке, кроме основной сборки, становятся закрытыми. Установка этого свойства неявно устанавливает для Internalize значение true.

Содержимое файла должно состоять из одного регулярного выражения на строку. Синтаксис определен в пространстве имен .NET System.Text.RegularExpressions для регулярных выражений. Регулярные выражения сопоставляются с полным именем каждого типа, например, «System.Collections.IList». Если совпадение не удается, выполняется повторная попытка с именем сборки (заключенным в квадратные скобки) перед именем типа. Таким образом, шаблон «[A].*» исключает возможность сделать все типы в сборке A непубличными. (Обратная косая черта необходима, поскольку строка обрабатывается как регулярное выражение.) Шаблон «N.T» будет соответствовать всем типам с именем T в пространстве имен с именем N независимо от того, в какой сборке они определены.

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

2.12 Усвоить

общественное логическое значение Internalize { get; набор; }

Это определяет, будет ли изменена видимость типов в сборках, отличных от основной сборки. Если оно равно true, то видимость всех неисключенных типов, видимых за пределами своей сборки, изменяется таким образом, что они не видны снаружи объединенной сборки. Тип освобождается, если его полное имя совпадает со строкой из ExcludeFile (раздел 2.10) с использованием механизма регулярных выражений .NET.

person Mightymuke    schedule 25.01.2013
comment
Жаль, что проголосовавший не оставил комментарий. Это то, что я делаю со своим проектом, и он работает хорошо, не уверен, в чем здесь проблема. - person Mightymuke; 29.01.2013
comment
Не уверен, но проблема была связана не с видимостью объединенных элементов, а с физическим включением этого элемента в сборку. Для которых варианты интернализации и исключения не имеют значения. - person NickSuperb; 07.02.2013