Скопируйте файлы в выходной каталог с помощью csproj dotnetcore

104

Итак, моя проблема довольно проста. У меня есть файлы, которые я хочу скопировать в выходной каталог сборки, будь то сборка отладки или публикация выпуска. Вся информация, которую я могу найти, касается старого подхода к конфигурации json. У кого-нибудь есть пример использования csproj с dotnetcore?

Ониуси
источник

Ответы:

144

Есть несколько способов достичь ваших целей, в зависимости от ваших потребностей.

Самый простой подход - условно установить элементы метаданных ( CopyToOutputDirectory/ CopyToPublishDirectory) (предполагается, .txtчто это Noneэлемент, а не Content, если он не работает, попробуйте <Content>вместо этого):

<ItemGroup Condition="'$(Configuration)' == 'Debug'">
  <None Update="foo.txt" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Если требуется больше контроля, наиболее универсальным подходом является добавление настраиваемых целей, которые подключаются к процессу сборки в файле csproj:

<Target Name="CopyCustomContent" AfterTargets="AfterBuild">
  <Copy SourceFiles="foo.txt" DestinationFolder="$(OutDir)" />
</Target>
<Target Name="CopyCustomContentOnPublish" AfterTargets="Publish">
  <Copy SourceFiles="foo.txt" DestinationFolder="$(PublishDir)" />
</Target>

Это копирует файл в соответствующие каталоги. Дополнительные параметры <Copy>задачи см. В ее документации . Чтобы ограничить это определенными конфигурациями, вы можете использовать Conditionатрибут:

<Target … Condition=" '$(Configuration)' == 'Release' ">

Этот Conditionатрибут может применяться как к <Target>элементу, так и к элементам задачи, например <Copy>.

Мартин Ульрих
источник
Как мне применить DestinationFolder к элементам <Reference>, или это возможно, в документах не так много, что я могу найти. Я не хочу, чтобы все мои сборки находились на корневом уровне, и предпочел бы, чтобы они находились в отдельной папке.
Reahreic,
Вы можете напрямую устанавливать DestinationSubDirectory="subdir\"метаданные для Referenceэлементов. Однако это означает, что вам нужно реализовать разрешение сборки самостоятельно ( событие AssemblyResolve )
Мартин Ульрих,
Как я могу скопировать родительскую папку, содержащую некоторые DLL в соответствующие папки. Я хочу сделать их доступными в выходном опубликованном пути, чтобы после сборки эти папки были доступны для моего приложения во время выполнения, поскольку я загружаю эти DLL в качестве подключаемых модулей при запуске. Я использую райдер на Mac
kuldeep
93

Хотя это помогло мне решить мою проблему, это не сработало для всех файлов в подкаталоге. Я также использовал Content Includeвместо Content Update;

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="layouts\*.*">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>  
  </ItemGroup>

</Project>
Мистер лось
источник
3
Каждая другая перестановка всех других ответов / предложений не сработала для меня. Никакого упоминания файла в подробных выводах сборки. Но ваше предложение здесь сработало.
user7817808 06
15
И если вы хотите включить промежуточные подпапки, используйте<Content Include="layouts\**\*.*">
JSancho
3
При использовании Web SDK ( <Project Sdk="Microsoft.NET.Sdk.Web">) он не позволит вам использовать, Include=потому что он уже, кажется, неявно указывает это в SDK. Мне пришлось использовать Update=его для сборки и включения дополнительных файлов.
notracs
Приятно, спасибо .. Но как скопировать в выходной каталог только содержимое папки, а не саму папку. Выражение assets\*.*должно предполагать это. Но он копирует всю папку с активами. Итак, у меня есть bin/Debug/netcoreapp3.1/assets/...Но я хочу, чтобы файлы папки с активами находились в корневом каталоге вывода. bin/Debug/netcoreapp3.1/....
Доминик
Я нашел решение: xml <Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <AssetsSourceFiles Include="assets/**/*.*"/> </ItemGroup> <Target Name="CopyCustomContent" AfterTargets="AfterBuild"> <Copy SourceFiles="@(AssetsSourceFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" /> </Target> </Project> (см. Мой ответ, чтобы узнать о лучшем формате кода.)
Доминик
15

Поместите это в свой .csproj файл, заменив nlog.config на желаемый путь к файлу. Затем просто сохраните его и создайте свой проект:

<ItemGroup>
  <Content Update="Nlog.config">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
Чад Куэн
источник
Это не похоже на копирование подкаталогов.
null
13

Предполагая, что у вас есть assetsпапка в корневом каталоге. Вы можете называть его как хотите. Это всего лишь пример:

ваш-проект.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <AssetsSourceFiles Include="assets/**/*.*"/>
  </ItemGroup>

  <Target Name="CopyCustomContent" AfterTargets="AfterBuild">
    <Copy SourceFiles="@(AssetsSourceFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
  </Target>
</Project>

это копирует только содержимое assetsпапки в выходной корень, не помещая его в assetsпапку. Но если вы хотите скопировать вместе с самой папкой, вы можете использовать следующий код:

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <Content Include="assets\**\*.*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>
Доминик
источник
3

У меня было требование, чтобы набор шаблонов HTML был потребляемым как на стороне клиента, так и на стороне сервера (Handlebars js)

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Content Update="wwwroot\html-templates\**\*.*">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

</Project>
hngr18
источник
0

Спасибо, что спасли меня, если вам нужно принудительно скопировать определенный пакет nuget в основной проект asp.net (2.2), добавьте в конец вашего csproj:

<!-- Force copy MathNet because we need it in compilation -->
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="Build">
    <PropertyGroup>
        <ErrorText>This project references NuGet package(s) that are missing on this computer. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll'))" />
</Target>

<ItemGroup>
    <ContentWithTargetPath Include="..\packages\MathNet.Numerics.4.8.1\lib\netstandard2.0\MathNet.Numerics.dll">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <TargetPath>MathNet.Numerics.dll</TargetPath>
    </ContentWithTargetPath>
</ItemGroup>
gab89
источник
0
<PropertyGroup>
    <PostBuildEvent>xcopy "$(ProjectDir)Xml" "$(ProjectDir)$(OutDir)Xml" /S /F /I /R /Y</PostBuildEvent>
</PropertyGroup>

или

<PropertyGroup>
    <PostBuildEvent>copy /Y "$(ProjectDir)MyXml.xml" "$(ProjectDir)$(OutDir)Xml"</PostBuildEvent>
</PropertyGroup>
Isxaker
источник
1
В идеале используйте задачу <Copy>, чтобы сделать ее кроссплатформенной.
Бруно Гарсия,