Copiare i file nella directory di output utilizzando csproj dotnetcore


103

Quindi il mio problema è piuttosto semplice. Ho alcuni file che desidero siano copiati nella directory di output della build, sia che si tratti di una build di debug o di una pubblicazione di rilascio. Tutte le informazioni che posso trovare riguardano il vecchio approccio di configurazione json. Qualcuno ha un esempio che usa il csproj con dotnetcore?

Risposte:


143

Ci sono diversi modi per raggiungere i tuoi obiettivi, a seconda delle tue esigenze.

L'approccio più semplice è impostare gli elementi dei metadati ( CopyToOutputDirectory/ CopyToPublishDirectory) in modo condizionale (supponendo che .txtsia un Noneelemento anziché Content, se non funziona, prova <Content>invece):

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

Se è necessario un maggiore controllo, l'approccio più versatile consiste nell'aggiungere target personalizzati che si agganciano al processo di compilazione nel file 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>

Questo copia un file nelle rispettive directory. Per ulteriori opzioni per l' <Copy>attività, vedere la relativa documentazione . Per limitare questo a determinate configurazioni, puoi utilizzare un Conditionattributo:

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

Questo Conditionattributo può essere applicato sia <Target>sull'elemento che su elementi di attività come <Copy>.


Come applicherei "DestinationFolder" agli elementi <Reference> o è possibile che sia possibile, non c'è molto nei documenti che riesco a trovare. Non voglio che tutti i miei assembly siano a livello di root e preferirei che si trovassero nella loro cartella.
Reahreic

Puoi impostare direttamente i DestinationSubDirectory="subdir\"metadati sugli Referenceelementi. Tuttavia, questo significa che devi implementare tu stesso la risoluzione dell'assembly ( evento AssemblyResolve )
Martin Ullrich

Come posso copiare la cartella principale che contiene alcune DLL nelle rispettive cartelle. Voglio renderli disponibili nel percorso pubblicato di output in modo che dopo aver creato queste cartelle siano disponibili per la mia applicazione in fase di esecuzione, mentre carico queste DLL come plugin all'avvio. Sto usando
Rider

93

Anche se questo mi ha aiutato a risolvere il problema, non ha funzionato per tutti i file in una sottodirectory. Ho anche usato Content Includepiuttosto che 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
Ogni altra permutazione di tutte le altre risposte / suggerimenti non ha funzionato per me. Nemmeno una menzione del file nell'output di compilazione dettagliato. Ma il tuo suggerimento qui ha funzionato.
user7817808

15
E se vuoi includere sottocartelle intermedie usa<Content Include="layouts\**\*.*">
JSancho

3
Quando si utilizza l'SDK Web ( <Project Sdk="Microsoft.NET.Sdk.Web">), non è possibile utilizzarlo Include=perché sembra già specificarlo implicitamente all'interno dell'SDK. Ho dovuto usarlo Update=per farlo costruire e includere i miei file aggiuntivi.
notracs

Bello, grazie .. Ma come copiare solo il contenuto della cartella nella directory di output non nella cartella stessa. L'espressione assets\*.*dovrebbe assumerlo. Ma copia l'intera cartella delle risorse. Quindi ho bin/Debug/netcoreapp3.1/assets/...Ma voglio i file della cartella degli asset nella directory principale dell'output. bin/Debug/netcoreapp3.1/....
Dominik

Ho trovato una soluzione: 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> (vedi la mia risposta per un formato di codice migliore.)
Dominik

15

Inseriscilo nel tuo file .csproj sostituendo nlog.config con il percorso file desiderato. Quindi salvalo e crea il tuo progetto:

<ItemGroup>
  <Content Update="Nlog.config">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

Questo non sembra copiare le sottodirectory.
null

13

Supponendo che tu abbia una assetscartella nella tua directory principale. Puoi nominarlo come vuoi. Questo è solo un esempio:

tuo-progetto.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>

questo copia solo il contenuto della assetscartella nella radice di output senza avvolgerlo nella assetscartella. Ma se vuoi copiare con la cartella stessa, puoi usare il seguente codice:

<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <Content Include="assets\**\*.*">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
</Project>

3

Avevo il requisito per una selezione di modelli HTML utilizzabili sia sul lato client che sul lato server (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>

0

Grazie salvami la giornata, se devi forzare la copia di un pacchetto nuget specifico in un progetto principale asp.net (2.2), aggiungi alla fine del tuo 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>

0
<PropertyGroup>
    <PostBuildEvent>xcopy "$(ProjectDir)Xml" "$(ProjectDir)$(OutDir)Xml" /S /F /I /R /Y</PostBuildEvent>
</PropertyGroup>

o

<PropertyGroup>
    <PostBuildEvent>copy /Y "$(ProjectDir)MyXml.xml" "$(ProjectDir)$(OutDir)Xml"</PostBuildEvent>
</PropertyGroup>

1
Idealmente utilizzare un'attività <Copia> per renderla multipiattaforma.
Bruno Garcia
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.