Visual Studio: как «Копировать в выходной каталог» без копирования структуры папок?

111

У меня есть несколько файлов dll в папке \ lib папки моего проекта. На странице свойств dll я выбрал «Действие сборки» как «Содержимое» и «Копировать в выходной каталог» как «Всегда копировать».

После сборки я фактически копирую dll, но они находятся внутри \ bin \ Release \ lib, а не в \ bin \ Release.

Есть ли способ скопировать файлы dll в \ bin \ Release (а не в \ bin \ Release \ lib) без написания сценария после сборки или использования nant и т. Д.?

О, Боже
источник

Ответы:

256

вместо <Content>использования <ContentWithTargetPath>и укажите целевой путь, например:

<ItemGroup>
  <ContentWithTargetPath Include="lib\some_file.dat">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <TargetPath>some_file.dat</TargetPath>
  </ContentWithTargetPath>
</ItemGroup>

Обратите внимание, что эта запись может быть не видна в Visual Studio (2012, 2015, 2017), но после добавления вручную в csproj она появится в Visual Studio. Однако целевой путь нельзя будет редактировать через пользовательский интерфейс.

Даниэль Цейтлин
источник
2
Я не вижу ContentWithTargetPath как параметр Build Action в VS 2015. Есть ли способ добавить его?
Ким
1
Как только я вручную добавляю запись в файл .csproj, она появляется как опция в среде IDE. Однако я все еще не могу редактировать целевой путь из среды IDE.
Ким
9
Меня беспокоит только то, что это перестанет поддерживаться в будущих версиях MSBuild / .NET / Visual Studio / Whatever, поскольку пользовательский интерфейс VS2015 не отображает этот параметр или свойство TargetPath.
MarioDS
1
У меня это работает. Ни один из других ответов не работает для меня. Это должен быть ответ.
GunWanderer
1
Обратите внимание, что с использованием ContentWithTargetPathинкрементальной компиляции breaks (проверено на VS 2017 15.9.9)
Mads Ravn
26

Сохраните их $(ProjectDir)\Lib, но добавьте эти файлы « как ссылку » в корень вашего .csproj. Теперь они будут скопированы в bin \ Debug (или любую другую выходную папку), не будучи в lib.

РЕДАКТИРОВАТЬ: этот ответ был написан еще тогда, когда ContentWithTargetPath не был доступен в версиях VS / MSBuild, которые я использовал. Оставьте этот ответ здесь для людей, которым, возможно, придется использовать более старую версию VS. Пожалуйста, перестаньте это комментировать, мы все знаем, что теперь есть способы получше.

Ани
источник
4
Спасибо, ananthonline. Я пробовал ваши шаги, но это не помогло. Может я что-то не так делаю. Вот что я делаю, исправьте, если вы считаете, что что-то не так: 1. Исключите эти библиотеки DLL из проекта, но оставьте их в библиотеке 2. Щелкните правой кнопкой мыши проект и «Добавить существующие элементы». Выберите библиотеки DLL из библиотеки и добавьте их «как ссылку» 3. Щелкните правой кнопкой мыши библиотеки DLL и снова выберите «Копировать всегда» в «Копировать в выходной каталог». 4. Очистить и восстановить. Результат: я снова получил эти dll в \ bin \ release \ lib
OhDear
1
Пожалуйста, опубликуйте снимок экрана с папкой вашего решения после его настройки
Ани
3
Если я попытаюсь добавить ссылку на файл, который уже находится в дереве проекта, он откажется и вместо этого просто снова
включит
1
Как и @Nyerguds, я заметил, что вы не можете добавить ссылку на файл, который уже находится в дереве проекта, поэтому этот ответ не решает вопрос.
Tore Østergaard
1
Не наводняет ли он корень каталога проекта в обозревателе решений? Со многими такими файлами это может быть проблемой. Обычно корень каталога проекта уже содержит слишком много различных файлов.
Alex34758
10

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

(Обратите внимание, что этот пост не дает прямого ответа на этот вопрос, так как он не сохраняет структуру папок и проекта, но я нашел этот подход полезным, потому что я смог реструктурировать свой проект в моем случае и потому, что я хотел избежать некоторых из недостатки других подходов здесь.)

меры

  • Щелкните правой кнопкой мыши свой Solution -> Add -> New Project -> Shared Project
  • Добавьте библиотеки DLL в этот проект (в корневой каталог этого проекта, а не в подпапку "lib")
  • (Убедитесь, что свойства файла DLL установлены правильно, например, Build Action: Contentи Copy to Output Directory: Copy Always)
  • Щелкните правой кнопкой мыши исходный проект References -> Add Reference -> Shared Projects
  • Выберите общий проект, который вы создали ранее

Настройка выглядит так:

Решение-проводник-скриншот

сынок
источник
2
Безусловно, простое и элегантное решение, позволяющее не загромождать проект.
Рави Ганеш
Я не мог заставить его работать с файлами UAP и * .bin.
Маттео
7

Добавьте dll-файлы в качестве ссылки на проект, а по ссылке установите «Копировать локально» в значение true.

erik_nw
источник
1
Спасибо, Эрик. Это отлично работает, за исключением одной dll, которую я не могу добавить в качестве ссылки. Ошибка, которую я получаю при добавлении в качестве ссылки: Не удалось добавить ссылку на «libeay32.dll». Убедитесь, что файл доступен и является допустимой сборкой или компонентом COM.
OhDear
7
@MAnthony: только сборки .NET или сборки взаимодействия COM могут быть добавлены в качестве ссылок на проект; родных DLL быть не может. Вам нужно будет найти другой способ скопировать DLL в \ bin \ Release.
Майкл Лю
Спасибо Эрику и Майклу и ananthonline. Извините, я не могу проголосовать за ваши ответы и комментарии, так как у меня нет необходимых очков репутации.
OhDear
1
Для неуправляемой DLL вам нужно будет использовать метод, который я предложил ниже.
Ani
4

Если вам нужно скопировать файлы из каталога Libs в корневую папку VS2017:

<ItemGroup Condition="'$(Platform)' == 'x64'">
    <None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

В любую другую папку, включая папку Libs (RecursiveDir)

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Дев-Сибирь
источник
3

В VisualStudio 2015 кажется, что если библиотеки DLL, которые вы «добавляете со ссылкой», находятся в подпапке того же проекта, они автоматически помещаются в папку, а вывод также помещается в папку, как вы видели.

Если библиотеки DLL находятся в другом проекте или каталоге на диске, а не во вложенной папке проекта , вы можете «Добавить со ссылкой», и они будут помещены в корневой каталог.

DefenestrationDay
источник
То же самое в VS2012. Он отказывается делать их ссылкой и просто добавляет их как контент. В конце концов, к сожалению, самым простым решением кажется сбросить их в корень проекта.
Nyerguds 06
0

Альтернативный метод - просто оставить элементы как тип None. В обозревателе решений щелкните те, которые вы хотите развернуть, и установите для Contentсвойства значение True.

Примечание: я делал это в VS2019, и все может меняться от версии к версии.

Чтобы это заработало, щелкните свой проект правой кнопкой мыши и выберите «Выгрузить проект». Затем щелкните правой кнопкой мыши выгруженный проект и выберите «Изменить имя_проекта.vcxproj».

В редакторе пройдите до конца файла и вставьте эту цель прямо перед конечным </Project>тегом:

  <Target Name="CopyContent" AfterTargets="Build">
    <Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
  </Target>

Теперь щелкните правой кнопкой мыши выгруженный проект и выберите «Перезагрузить проект». Выберите, чтобы сохранить и закрыть, если вам будет предложено.

Я также установил OutputDirectory:

$(SolutionDir)bin\$(Configuration)\$(Platform)\

и IntermediateDirectoryк:

$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\

на странице Project Properties General. Результат будет помещен в папку «bin», а промежуточные продукты - в папку «obj» в корне вашего решения.

Примечание. $(SolutionDir)Не определяется при запуске MSBuild из командной строки. Есть уловка, которую вы можете использовать, чтобы определить это для папки, в которой находится файл .sln, с помощью GetDirectoryNameOfFileAbove. (оставлено в качестве упражнения для читателя). Кроме того, похоже, что в 2019 году они все равно правильно обрабатывают это в командной строке. Да :) В $(SolutionDir)конце есть обратная косая черта, поэтому после нее нет. Результат каждого должен иметь обратную косую черту в конце.

Теперь, если у вас есть версия Pro или выше, пожалуйста, не делайте этого каждый раз, когда вам нужно создать проект. Это было бы глупо. Вместо этого, когда ваш проект настроен так, как вам нравится, выберите Project -> Export Template. Вы даете ему имя, и в следующий раз, когда захотите создать такой же проект, просто выберите это имя в диалоговом окне «Новый проект». (В более старой версии, я думаю, это было Files -> Export Teamplate....)

ChuckEng
источник
-1

У меня была такая же проблема с Visual Studio 2010 / C # Project.

Для сборок (то есть с интерфейсом .NET) используйте папку «Ссылки» в вашем проекте в обозревателе решений. Щелкните его правой кнопкой мыши, выберите «Добавить существующий элемент» и найдите сборку .dll.

Общие файлы .dll можно поместить в подпапку (как упоминалось выше "\ lib") и в свойствах выбрать:

  • Build Action = "HelpFiles"
  • Копировать в OutputDirectory = "Если новее"

У меня это сработало именно так, как я и хотел - во время сборки .DLL копируются в выходной каталог без подпапки "\ lib".

Петр Хендль
источник