Как заставить Visual Studio скопировать файл DLL в выходной каталог?

102

У меня есть проект Visual Studio C ++, который использует внешний файл DLL. Как я могу заставить Visual Studio автоматически копировать этот файл DLL в выходной каталог (отладка / выпуск) при сборке проекта?

Мат
источник

Ответы:

92

Используйте в проекте действие после сборки и добавьте команды для копирования вредоносной библиотеки DLL. Действия после сборки записываются как пакетный сценарий.

На выходной каталог можно ссылаться как на $(OutDir). Каталог проекта доступен как $(ProjDir). Попробуйте использовать относительные пути, где это возможно, чтобы вы могли копировать или перемещать папку проекта, не нарушая действия после сборки.

Адриан Плиссон
источник
26
Также стоит отметить, что он может установить событие после сборки через Project> Properties> Build Events> Post-Build Event.
Фил Бут
21
Образец: eyeung003.blogspot.com/2009/11/...
AntonioR
38
В случае разрыва ссылки: "xcopy / y" $ (ProjectDir) *. Dll "" $ (OutDir) "
ace
Я изменил приведенное выше на то, как я лично использую команду в своих экземплярах. Это будет; копировать файлы только для чтения, которые подходят для системы управления версиями, и создает целевой каталог (обычно не требуется). -> xcopy "$ (ProjectDir) *. dll" "$ (OutDir)" / i / r / y
Eat at Joes
8
Добавьте флаг / d в xCopy, чтобы предотвратить ненужное повторное копирование файлов, которые не изменились в выходном каталоге.
Zoey
45

$ (OutDir) оказался относительным путем в VS2013, поэтому мне пришлось объединить его с $ (ProjectDir) для достижения желаемого эффекта:

xcopy /y /d  "$(ProjectDir)External\*.dll" "$(ProjectDir)$(OutDir)"

Кстати, вы можете легко отлаживать сценарии, добавляя «echo» в начале и наблюдая за развернутым текстом в окне вывода сборки.

Нешо Нешев
источник
3
$ (TargetDir) может заменить $ (ProjectDir) $ (OutDir), потому что в любом случае это комбинация обоих.
person27
В моем случае без / d он выдавал ошибку «Доступ запрещен». Но / d согласно документации актуален. Не уверен, какая связь.
Ravi C
1
Добавление / d предотвращает перезапись, если исходный файл старше или совпадает с существующим. Ошибка отказа в доступе может возникнуть, если цель заблокирована другим процессом.
Rich Shealer
7

Подробности в разделе комментариев выше не помогли мне (VS 2013) при попытке скопировать выходную dll из одного проекта C ++ в папку выпуска и отладки другого проекта C # в том же решении.

Мне пришлось добавить следующее действие после сборки (щелкните правой кнопкой мыши проект с выходом .dll), затем свойства -> свойства конфигурации -> события сборки -> событие после сборки -> командная строка

теперь я добавил эти две строки, чтобы скопировать выходную dll в две папки:

xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Release
xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Debug
SCBuergel.eth
источник
5

(Этот ответ относится только к C #, а не к C ++, извините, я неправильно прочитал исходный вопрос)

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

Это должно быть частью .NET или инфраструктуры pinvoke, поскольку это очень полезно ... Это упрощает управление вашей управляемой DLL как с помощью Xcopy, так и в качестве ссылки на проект в более крупном решении Visual Studio. Как только вы это сделаете, вам не придется беспокоиться о событиях после сборки.

ОБНОВИТЬ:

Я разместил код здесь в другом ответе https://stackoverflow.com/a/11038376/364818

Марк Лаката
источник
1
Я согласен, он должен быть частью фреймворка (статически связывать библиотеки DLL и т. Д.). Стоит отметить, что сохранение библиотеки DLL в качестве ресурса с последующим ее извлечением во время выполнения может вызвать проблемы в некоторых корпоративных средах (особенно если у них достаточно проактивное антивирусное ПО).
BrainSlugs83
1

Добавьте встроенную копию в файл project.csproj :

  <Project>
    ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Debug\bin" SkipUnchangedFiles="false" />
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Release\bin" SkipUnchangedFiles="false" />
    </Target>
  </Project>
John_J
источник
В VS есть долгосрочная ошибка, используйте ProjectDir, а не SolutionDir
John_J
0
xcopy /y /d  "$(ProjectDir)External\*.dll" "$(TargetDir)"

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

xcopy /y /d  "$(ProjectDir)..\External\*.dll" "$(TargetDir)"

В /yопционные копии без подтверждения. Эта /dопция проверяет, существует ли файл в целевом объекте, и копирует ли он, только если у источника более новая временная метка, чем у цели.

Я обнаружил, что по крайней мере в более новых версиях Visual Studio, таких как VS2109, $(ProjDir)не определено и пришлось использовать $(ProjectDir)вместо него.

Если не указывать целевую папку, по xcopyумолчанию должен использоваться выходной каталог. Важно понимать, что сам по $(OutDir)себе разум бесполезен.

$(OutDir), по крайней мере, в последних версиях Visual Studio, определяется как относительный путь к выходной папке, например bin/x86/Debug. Использование только его в качестве цели создаст новый набор папок, начиная с выходной папки проекта. Пример: … bin/x86/Debug/bin/x86/Debug.

Объединение его с папкой проекта должно привести вас в нужное место. Пример: $(ProjectDir)$(OutDir).

Однако $(TargetDir)предоставит выходной каталог за один шаг.

Список макросов MSBuild от Microsoft для текущей и предыдущих версий Visual Studio

Богатый лекарь
источник