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


85

У мене є проект C #, який називає MyProject.csproj, розташований за адресою "C: \ Projects \ MyProject \". У мене також є файли, які я хочу скопіювати у вихідний каталог цього проекту. Але файли знаходяться в розташуванні "C: \ MyContentFiles \", тобто вони НЕ знаходяться в конусі проекту. Цей каталог також має підкаталоги. Вмістом каталогу не управляється. Отже, я повинен включити все, що знаходиться під ним.

Коли я включаю їх як "Вміст" у проект, вони копіюються, але структура каталогів втрачається. Я зробив щось подібне: -

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

Як копіювати ці файли / каталоги рекурсивно у вихідний каталог проекту із збереженою структурою каталогів?

Відповіді:


55

Вам потрібно додати файл як посилання:

  1. Клацніть правою кнопкою миші на проект у VS.
  2. Додати -> Існуючий елемент ...
  3. Знайдіть файл.
  4. Виберіть його та.
  5. Додати як посилання (спадне меню в кнопці Додати в діалоговому вікні).
  6. Відкрийте властивості файлу та встановіть для параметра «Копіювати у вихідний каталог» значення «Копіювати завжди».

АЛЕ ви не можете зробити це для дерева каталогів.
Натомість для цього вам потрібно написати завдання після збірки. Це зразок, який змусить вас дивитись.


8
Як зазначено у цій відповіді , "Ви не можете зробити це для дерева каталогів." твердження не відповідає дійсності.
Mandark

160

Я вважаю, що @Dmytrii це зрозуміло з одного боку - ви хочете скористатися функцією "посилання".

Однак, він лише частково правильний, коли каже, що не може зробити посилання на дерево каталогів. Хоча це справді так, коли намагається додати посилання за допомогою графічного інтерфейсу Visual Studio, MSBuild це підтримує.

Якщо ви хочете зберегти структуру каталогів, просто додайте %(RecursiveDir)тег до свого <link>вузла:

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

Сторінка Відомі метадані елементів MSBuild детальніше описує метадані, до яких ви маєте доступ.


1
1) Що станеться, якщо файл буде видалено із сховища спільних активів? Не схоже, що його буде видалено з Solution Dir 2) Чи є спосіб отримати Visual Studio для видалення цих файлів із $ (SolutionDir) після завершення запуску. Залишення їх там може заплутати інших розробників.
Адам

@Adam Див. Мою відповідь нижче
Робін ван дер Кнаап,

8
Будучи розбитим у пустелі з невеликою кількістю їжі, води та гострою потребою в спілкуванні, я вважаю цю відповідь корисною. Дотримуючись цих інструкцій, я зміг створити повністю функціональний ШІ, який тепер замінив усі людські потреби, які колись переслідували мене в пустелі тут. Дякую Mandark!
deepelement

1
@Vijay перегляньте мою редакцію, вам потрібно <Content Include="..\..\MyContentFiles\**\*.*">- зверніть увагу \*.*на кінець шляху.
CAD хлопець

2
Не працює для проекту .NET Core на VS2017 (15.8.6).
zwcloud

29

Відповідь Mandark додає файли вмісту безпосередньо до рішення, і вони з’являться у досліднику рішень. Щоразу, коли файл додається або видаляється в оригінальному каталозі, Visual Studio не забирає його автоматично. Крім того, щоразу, коли файл видаляється або додається у провіднику рішень, файл проекту змінюється, і всі файли включаються окремо, замість того, щоб просто включати папку.

Щоб цього не сталося, ви можете використовувати той самий фокус, але помістіть його в окремий файл проекту, а потім імпортуйте.

Файл проекту (наприклад, 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


1
З якихось причин це, здається, не спрацювало для мене, використовуючи файл .proj, але я зміг змусити його працювати з файлом .csproj.
StriplingWarrior

6
Ви можете додати <Visible> true </Visible> до елементу Content, щоб елементи відображались у Провіднику рішень.
Michael Baker

У мене все було в порядку .proj
Jason Dufair

Це взагалі не спрацювало для мене, і я припускаю, що це тому, що елементи, які потрібно пов’язати, самі були створені в події попередньої збірки.
Paul K

2
Не працює для проекту .NET Core на VS2017 (15.8.6).
zwcloud

10

Далі, які ви додасте внизу файлу проекту, буде скопійовано файли вмісту, що підтримують структуру каталогів у події після побудови, до цільового каталогу $(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" />

1
Ваші перетворення мають тип-o: @ (ExtraContent) -> '...') має бути @ (ExtraContext -> '...'). Інакше хороша відповідь!
alexdej

@Todd 1) Що станеться, якщо файл буде видалено з магазину MyContentFiles? Не схоже, що його буде видалено з Solution Dir 2) Чи є спосіб отримати Visual Studio для видалення цих файлів із $ (SolutionDir) після завершення запуску. Залишення їх там може заплутати інших розробників.
Адам

3

я думаю

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

Цього достатньо, оскільки вам потрібно все в цій папці та підпапках


2

Щоб включити файли в папку для проекту .NET Core,

<!--Just files-->
<ItemGroup>
  <None Update="..\..\MyContentFiles\**\*.*">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>
<!--Content files-->
<ItemGroup>
  <Content Include="..\..\MyContentFiles\**\*.*" Link="MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

А властивість елементів "Копіювати до вихідного каталогу" буде "Копіювати, якщо новіша":
Скопіювати, якщо новіше


-1

Щоб проігнорувати файл у проекті .Net Core:

<ItemGroup>
 <Content Include="appsettings.local.json">
   <CopyToOutputDirectory Condition="Exists('appsettings.local.json')">PreserveNewest</CopyToOutputDirectory>
 </Content>
</ItemGroup>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.