Kopieren Sie Dateien mit csproj dotnetcore in das Ausgabeverzeichnis

93

Mein Problem ist also ziemlich einfach. Ich habe einige Dateien, die in das Build-Ausgabeverzeichnis kopiert werden sollen, unabhängig davon, ob es sich um einen Debug-Build oder eine Release-Veröffentlichung handelt. Alle Informationen, die ich finden kann, beziehen sich auf den alten json-Konfigurationsansatz. Hat jemand ein Beispiel mit dem csproj mit dotnetcore?

Theyouthis
quelle

Antworten:

130

Es gibt einige Möglichkeiten, um Ihre Ziele zu erreichen, je nachdem, welche Bedürfnisse Sie haben.

Der einfachste Ansatz besteht darin, die Metadaten ( CopyToOutputDirectory/ CopyToPublishDirectory) -Elemente bedingt festzulegen (vorausgesetzt, .txtes handelt sich um ein NoneElement, anstatt Contentes zu versuchen, wenn es nicht funktioniert <Content>):

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

Wenn mehr Kontrolle erforderlich ist, besteht der vielseitigste Ansatz darin, benutzerdefinierte Ziele hinzuzufügen, die in den Erstellungsprozess in der csproj-Datei eingebunden sind:

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

Dadurch wird eine Datei in die jeweiligen Verzeichnisse kopiert. Weitere Optionen für die <Copy>Aufgabe finden Sie in der Dokumentation . Um dies auf bestimmte Konfigurationen zu beschränken, können Sie ein ConditionAttribut verwenden:

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

Dieses ConditionAttribut kann sowohl auf das <Target>Element als auch auf Aufgabenelemente wie angewendet werden <Copy>.

Martin Ullrich
quelle
Wie würde ich 'DestinationFolder' auf <Referenz> -Elemente anwenden, oder ist es möglich, dass die Dokumente nicht viel enthalten, was ich finden kann? Ich möchte nicht, dass sich alle meine Assemblys auf der Stammebene befinden, und möchte, dass sie sich in einem eigenen Ordner befinden.
Reahreic
Sie können DestinationSubDirectory="subdir\"Metadaten für ReferenceElemente direkt festlegen . Dies bedeutet jedoch, dass Sie die Assemblyauflösung selbst implementieren müssen ( AssemblyResolve-Ereignis )
Martin Ullrich,
Wie kann ich einen übergeordneten Ordner kopieren, der einige DLLs in den jeweiligen Ordnern enthält? Ich möchte sie im veröffentlichten Ausgabepfad verfügbar machen, damit diese Ordner nach dem Erstellen zur Laufzeit für meine Anwendung verfügbar sind, da ich diese DLLs beim Start als Plugins lade. Ich benutze Rider auf Mac
Kuldeep
87

Dies half mir zwar, mein Problem zu lösen, funktionierte jedoch nicht für alle Dateien in einem Unterverzeichnis. Ich habe auch Content Includeeher verwendet als 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>
Herr Elch
quelle
3
Jede andere Permutation aller anderen Antworten / Vorschläge hat bei mir nicht funktioniert. Nicht einmal eine Erwähnung der Datei in der ausführlichen Build-Ausgabe. Aber Ihr Vorschlag hier hat funktioniert.
user7817808
14
Und wenn Sie Zwischenunterordner <Content Include="layouts\**\*.*">
einschließen
3
Wenn Sie das Web SDK ( <Project Sdk="Microsoft.NET.Sdk.Web">) verwenden, können Sie es nicht verwenden, Include=da dies bereits implizit im SDK angegeben zu sein scheint. Ich musste es verwenden Update=, um es zu erstellen und meine zusätzlichen Dateien einzuschließen.
Notracs
Schön, danke. Aber wie kopiere ich nur den Inhalt des Ordners in das Ausgabeverzeichnis, nicht in den Ordner selbst? Der Ausdruck assets\*.*sollte es annehmen. Es wird jedoch der gesamte Assets-Ordner kopiert. Ich habe bin/Debug/netcoreapp3.1/assets/...aber ich möchte die Dateien des Assets-Ordners in das Stammverzeichnis der Ausgabe. bin/Debug/netcoreapp3.1/....
Dominik
Ich habe eine Lösung gefunden: 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> (Ein besseres Codeformat finden Sie in meiner Antwort.)
Dominik
15

Fügen Sie dies in Ihre .csproj-Datei ein und ersetzen Sie nlog.config durch den gewünschten Dateipfad. Dann speichern Sie es einfach und erstellen Sie Ihr Projekt:

<ItemGroup>
  <Content Update="Nlog.config">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
Chad Kuehn
quelle
Dies scheint keine Unterverzeichnisse zu kopieren.
null
8

Angenommen, Sie haben einen assetsOrdner in Ihrem Stammverzeichnis. Sie können es benennen, wie Sie möchten. Dies ist nur ein Beispiel:

your-project.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>

Dadurch wird nur der Inhalt des assetsOrdners in das Ausgabestammverzeichnis kopiert, ohne ihn in den assetsOrdner einzuschließen. Wenn Sie jedoch mit dem Ordner selbst kopieren möchten, können Sie den folgenden Code verwenden:

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

Ich hatte die Anforderung, dass eine Auswahl von HTML-Vorlagen sowohl clientseitig als auch serverseitig verwendet werden kann (Lenker 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
quelle
0

Vielen Dank, dass Sie meinen Tag retten. Wenn Sie das Kopieren eines bestimmten Nuget-Pakets in ein asp.net-Kernprojekt (2.2) erzwingen müssen, fügen Sie am Ende Ihres csproj Folgendes hinzu:

<!-- 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
quelle
0
<PropertyGroup>
    <PostBuildEvent>xcopy "$(ProjectDir)Xml" "$(ProjectDir)$(OutDir)Xml" /S /F /I /R /Y</PostBuildEvent>
</PropertyGroup>

oder

<PropertyGroup>
    <PostBuildEvent>copy /Y "$(ProjectDir)MyXml.xml" "$(ProjectDir)$(OutDir)Xml"</PostBuildEvent>
</PropertyGroup>
isxaker
quelle
Verwenden Sie im Idealfall eine <Copy> -Aufgabe, um sie plattformübergreifend zu gestalten.
Bruno Garcia