Включая файлы содержимого в .csproj, которые находятся за пределами проектного конуса

У меня есть проект С#, который говорит MyProject.csproj, расположенный в "C:\Projects\MyProject". У меня также есть файлы, которые я хочу скопировать в выходной каталог этого проекта. Но файлы находятся в месте "C:\MyContentFiles \", то есть они НЕ входят в конус проекта. Этот каталог также имеет подкаталоги. Содержимое каталога не управляется. Поэтому я должен включить все, что находится под ним.

Когда я включаю их как "Контент" в проект, они копируются, но структура каталогов теряется. Я сделал что-то вроде этого: -

<Content Include="..\..\MyContentFiles\**">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Как скопировать эти файлы/каталоги рекурсивно в выходной каталог проекта с сохраненной структурой каталогов?

Ответ 1

Вам нужно добавить файл в качестве ссылки:

  • Щелкните правой кнопкой мыши на проекте в VS.
  • Добавить → Существующий элемент...
  • Найти файл.
  • Выберите его и.
  • Добавьте в качестве ссылки (выпадающий в кнопке Добавить в диалоговом окне).
  • Откройте свойства файла и установите "Копировать в каталог вывода" на "Копировать всегда".

НО вы не можете сделать это для дерева каталогов.
Вместо этого вам нужно написать пост-сборку для этого. Это образец, который заставит вас смотреть.

Ответ 2

Я считаю, @Dmytrii с одной стороны - вы хотите использовать функцию "ссылка".

Однако он лишь частично исправляет, говоря, что вы не можете ссылаться на дерево каталогов. Хотя это действительно верно при попытке добавить ссылки с помощью Visual Studio GUI, MSBuild поддерживает это.

Если вы хотите сохранить структуру каталогов, просто добавьте тег %(RecursiveDir) в свой <link> node:

<Content Include="..\..\MyContentFiles\**\*.*">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Страница MSBuild Известные метаданные элементов более подробно описывают доступные метаданные.

Ответ 3

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

Чтобы предотвратить это, вы можете использовать один и тот же трюк, но поместите его в отдельный файл проекта и затем импортируйте его.

Файл проекта (например, include.proj) выглядит следующим образом:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="..\..\MyContentFiles\**">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

В вашем собственном файле проекта добавьте следующую строку

<Import Project="include.proj" />

Visual Studio не будет связываться с этим файлом и просто добавляет файлы в качестве контента во время сборки. Изменения в исходном каталоге всегда включены. Файлы не будут отображаться в вашем проводнике решений, но будут включены в выходной каталог.

Поднял этот трюк здесь: http://blogs.msdn.com/b/shawnhar/archive/2007/06/06/wildcard-content-using-msbuild.aspx

Ответ 4

Следующее, которое вы добавили бы к нижней части файла проекта, скопирует ваши файлы содержимого, поддерживающие структуру каталогов в событии после сборки, в целевой каталог $(TargetDirectory) вашей сборки (обычно $(MSBuildProjectDirectory)\bin\Debug).

<ItemGroup>
    <ExtraContent Include="$(MSBuildProjectDirectory)\..\..\MyContentFiles\**" />
</ItemGroup>

<Target Name="AfterBuild">
    <Copy 
        SourceFiles="@(ExtraContent)" 
        DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
        SkipUnchangedFiles="true" />
</Target>

Если эти файлы нужно зайти в каталог с именем MyContentFiles, вы можете добавить это перед копией:

<MakeDir Directories="$(TargetDir)\MyContentFiles" Condition=" !Exists('$(TargetDir\MyContentFiles') " />

и измените

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />

Для

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />

Ответ 5

Я думаю,

<Content Include="..\..\MyContentFiles\**\*.*">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Достаточно просто, так как вам нужно все в этой папке и вложенных папках