.NET - встраивание ссылочных DLL в EXE, когда они являются ссылками на проект - PullRequest
1 голос
/ 07 октября 2011

У меня есть решение VS, которое содержит три проекта - один создает EXE, а два других - DLL сборки. Это организовано таким образом, потому что библиотеки DLL содержат код, который используется совместно с другими файлами EXE. Когда я развертываю EXE, я хочу иметь возможность просто скопировать EXE в каталог bin и запустить его без необходимости копировать дополнительные DLL. Это особенно важно, потому что другие EXE-файлы в каталоге bin будут созданы на основе более ранних версий DLL.

Итак, я включил библиотеки DLL, созданные из двух проектов в мой EXE-файл, в качестве встроенных ресурсов и подключил AppDomain.CurrentDomain.AssemblyResolve для загрузки их при запуске EXE.

И это работает, кроме двух вещей:

  1. Каждый проект DLL фактически создает две библиотеки DLL, одну, когда для конфигурации задано «Отладка», и другую, когда для конфигурации выбрано «Release». Было бы неплохо включить правильную сборку в соответствующую сборку. И
  2. Если библиотеки DLL еще не существуют, сборка завершается неудачей.

Это вторая проблема, которая является настоящей. Если библиотеки DLL уже существуют, сборка выполняется нормально. Но если библиотеки DLL отсутствуют, сборка завершается неудачно. Поэтому добавление этих зависимостей работает только в том случае, если я сначала строю решение без зависимостей, а затем добавляю их.

Что, конечно, не сработает. Мне нужно решение, которое будет построено из чистой проверки.

Итак, есть идеи?

Ответы [ 3 ]

2 голосов
/ 29 октября 2014

Я нашел это решение где-то в блоге, но это было недавно, и я потерял ссылку.

Вы можете добавить пользовательскую цель, отредактировав файл проекта вручную, как показано ниже. Таким образом, автоматически внедряются ВСЕ ссылки, поэтому вам не нужно ничего делать вручную после добавления / удаления ссылки. Это также позволяет вам иметь различные значения $(ConfigurationName) для разных проектов.

<Project>

  ...

  <!-- Custom target - this includes all dll references as embedded resources during build. -->
  <Target Name="AfterResolveReferences">
    <ItemGroup>
      <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
        <LogicalName>%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
      </EmbeddedResource>
    </ItemGroup>
  </Target>
</Project>

Имя встроенного ресурса будет AssemblyName.dll для каждой из встроенных сборок. Если вы хотите загрузить эти библиотеки во время выполнения, вы можете сделать что-то похожее на это:

private void LoadAssemblyFromResource(string assemblyName)
{
    if (!assemblyName.EndsWith(".dll"))
        assemblyName += ".dll";
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    using (Stream stream = executingAssembly.GetManifestResourceStream(assemblyName))
    {
        if (stream == null)
            throw new ArgumentException("Embedded assembly not found: " + assemblyName, "assemblyName");
        byte[] assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
        Assembly.Load(assemblyRawBytes);
    }
}
1 голос
/ 07 октября 2011

ОК, вот проблема.Каждый из проектов DLL создает копию своей библиотеки DLL в своей папке проекта ./bin/Release/ или ./bin/Debug/.

Вы не можете включить их в качестве встроенных ресурсов в проект EXE, потому что они не находятся в папке проекта EXE.

Когда проект EXE завершает сборку, он копирует библиотеки DLL проекта в свои собственные ./bin/Release/ или .bin / Debug /.Поскольку эти скопированные файлы находятся в папке проекта EXE, вы можете включить их в качестве встроенных ресурсов, за исключением того, что вы не хотите, потому что они не существуют, пока сборка не будет завершена, и сборка не будет завершена, если они не будут выполнены.'t there.

Решение состоит в том, чтобы поместить копию библиотек DLL где-то еще в папку проекта EXE и включить эти копии в сборку в качестве встроенных ресурсов.Я вставил их в ./DLLs/.

И затем, чтобы исключить необходимость их копирования вручную, я добавил событие предварительной сборки:

COPY $(SolutionDir)\myDLL\bin\$(ConfigurationName)\myDLL.dll $(ProjectDir)\DLLs

Обратите внимание, как это будет копироватьлибо отладочная, либо выпускная версия DLL, в зависимости от того, что я собираю.

0 голосов
/ 07 октября 2011

Я никогда не использовал это, но ILMerge должен быть в состоянии справиться с этим. После того, как вы соберете свой проект, передайте свой исполняемый файл и dll в ILMerge и дайте ему создать одну мастер-сборку для вас.

http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx

...