Skopiuj pliki do katalogu wyjściowego przy użyciu csproj dotnetcore

109

Więc mój problem jest dość prosty. Mam kilka plików, które chcę skopiować do katalogu wyjściowego kompilacji, niezależnie od tego, czy jest to kompilacja debugowania, czy publikacja wydania. Wszystkie informacje, które mogę znaleźć, dotyczą starego podejścia do konfiguracji json. Czy ktoś ma przykład używający csproj z dotnetcore?


źródło

Odpowiedzi:

148

Istnieje kilka sposobów osiągnięcia swoich celów, w zależności od Twoich potrzeb.

Najprostszym podejściem jest warunkowe ustawienie elementów metadanych ( CopyToOutputDirectory/ CopyToPublishDirectory) (zakładając .txt, że jest to Noneelement, a Contentjeśli nie działa, spróbuj <Content>zamiast tego):

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

Jeśli wymagana jest większa kontrola, najbardziej wszechstronnym podejściem jest dodanie niestandardowych celów, które przechodzą do procesu kompilacji w pliku 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>

Spowoduje to skopiowanie pliku do odpowiednich katalogów. Więcej opcji dotyczących <Copy>zadania można znaleźć w jego dokumentacji . Aby ograniczyć to do określonych konfiguracji, możesz użyć Conditionatrybutu:

<TargetCondition=" '$(Configuration)' == 'Release' ">

Ten Conditionatrybut można zastosować zarówno do <Target>elementu, jak i do elementów zadania, takich jak <Copy>.

Martin Ullrich
źródło
Jak zastosować „DestinationFolder” do elementów <Reference>, czy jest to możliwe, w dokumentach nie ma zbyt wiele do znalezienia. Nie chcę, aby wszystkie moje zestawy znajdowały się na poziomie głównym i wolę, aby znajdowały się we własnym folderze.
Reahreic
Możesz ustawić DestinationSubDirectory="subdir\"metadane Referenceelementów bezpośrednio. Oznacza to jednak, że musisz samodzielnie wdrożyć rozwiązanie zespołu ( wydarzenie AssemblyResolve )
Martin Ullrich
Jak mogę skopiować folder nadrzędny, który zawiera niektóre biblioteki DLL w odpowiednich folderach. Chcę, aby były dostępne w wyjściowej ścieżce publikacji, aby po skompilowaniu tych folderów były dostępne dla mojej aplikacji w czasie wykonywania, ponieważ ładuję te biblioteki DLL jako wtyczki podczas uruchamiania. Używam ridera na
Macu
97

Chociaż pomogło mi to w rozwiązaniu problemu, nie działało w przypadku wszystkich plików w podkatalogu. Użyłem też Content Includezamiast 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>
Panie Łoś
źródło
3
Każda inna kombinacja wszystkich pozostałych odpowiedzi / sugestii nie działała dla mnie. Nie ma nawet wzmianki o pliku w szczegółowym wyjściu kompilacji. Ale twoja sugestia tutaj zadziałała.
user7817808,
16
A jeśli chcesz uwzględnić pośrednie podfoldery, użyj<Content Include="layouts\**\*.*">
JSancho,
3
Podczas korzystania z zestawu SDK sieci Web ( <Project Sdk="Microsoft.NET.Sdk.Web">) nie pozwala na użycie, Include=ponieważ wydaje się, że już niejawnie określa to w zestawie SDK. Musiałem go użyć Update=, aby skompilować i dołączyć moje dodatkowe pliki.
notracs
Fajnie, dziękuję .. Ale jak skopiować tylko zawartość folderu do katalogu wyjściowego, a nie sam folder. Wyrażenie assets\*.*powinno to przyjąć. Ale kopiuje cały folder zasobów. Więc mam, bin/Debug/netcoreapp3.1/assets/...ale chcę, aby pliki folderu zasobów do katalogu głównego danych wyjściowych. bin/Debug/netcoreapp3.1/....
Dominik
Znalazłem rozwiązanie: 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> (zobacz moją odpowiedź dla lepszego formatu kodu.)
Dominik
15

Zakładając, że masz assetsfolder w katalogu głównym. Możesz nazwać to, jak chcesz. To tylko przykład:

twój-projekt.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>

kopiuje to tylko zawartość assetsfolderu do wyjściowego katalogu głównego bez zawijania go do assetsfolderu. Ale jeśli chcesz skopiować z samym folderem, możesz użyć następującego kodu:

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <Content Include="assets\**\*.*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>
Dominik
źródło
15

Umieść to w swoim pliku .csproj, zastępując nlog.config żądaną ścieżką do pliku. Następnie po prostu zapisz go i zbuduj swój projekt:

<ItemGroup>
  <Content Update="Nlog.config">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
Chad Kuehn
źródło
Wygląda na to, że nie powoduje to kopiowania podkatalogów.
zerowy
3

Wymagałem, aby wybór szablonów HTML był możliwy do wykorzystania zarówno po stronie klienta, jak i po stronie serwera (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
źródło
0
<PropertyGroup>
    <PostBuildEvent>xcopy "$(ProjectDir)Xml" "$(ProjectDir)$(OutDir)Xml" /S /F /I /R /Y</PostBuildEvent>
</PropertyGroup>

lub

<PropertyGroup>
    <PostBuildEvent>copy /Y "$(ProjectDir)MyXml.xml" "$(ProjectDir)$(OutDir)Xml"</PostBuildEvent>
</PropertyGroup>
isxaker
źródło
1
Najlepiej użyj zadania <Copy>, aby uczynić go międzyplatformowym.
Bruno Garcia
0

Jeśli musisz wymusić skopiowanie określonego pakietu NuGet do projektu ASP.NET Core (2.2), dodaj na końcu swojego 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
źródło