Copie los archivos al directorio de salida usando csproj dotnetcore


103

Entonces mi problema es bastante simple. Tengo algunos archivos que quiero que se copien en el directorio de salida de la compilación, ya sea una compilación de depuración o una publicación de lanzamiento. Toda la información que puedo encontrar es sobre el antiguo enfoque de configuración json. ¿Alguien tiene un ejemplo usando el csproj con dotnetcore?

Respuestas:


143

Hay varias formas de lograr sus objetivos, según cuáles sean sus necesidades.

El enfoque más fácil es configurar los elementos de metadatos ( CopyToOutputDirectory/ CopyToPublishDirectory) de forma condicional (asumiendo que .txtes un Noneelemento en lugar de Content, si no funciona, intente en su <Content>lugar):

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

Si se requiere más control, el enfoque más versátil es agregar destinos personalizados que se enganchan en el proceso de compilación en el archivo 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>

Esto copia un archivo a los directorios respectivos. Para obtener más opciones para la <Copy>tarea, consulte su documentación . Para limitar esto a ciertas configuraciones, puede utilizar un Conditionatributo:

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

Este Conditionatributo se puede aplicar tanto en el <Target>elemento como en elementos de tarea como <Copy>.


¿Cómo aplicaría 'DestinationFolder' a los elementos <Reference>, o si es posible, no hay mucho en los documentos que pueda encontrar. No quiero que todos mis ensamblados estén en el nivel raíz y preferiría que estuvieran en su propia carpeta.
Reahreic

Puede establecer DestinationSubDirectory="subdir\"metadatos en Referenceelementos directamente. Sin embargo, esto significa que debe implementar la resolución de ensamblaje usted mismo ( evento AssemblyResolve )
Martin Ullrich

¿Cómo puedo copiar la carpeta principal que contiene algunos archivos DLL en las carpetas respectivas? Quiero que estén disponibles en la ruta de salida publicada para que, después de compilar estas carpetas, estén disponibles para mi aplicación en el tiempo de ejecución, ya que cargo estos dlls como complementos al inicio. Estoy usando rider en mac
kuldeep

93

Si bien esto me ayudó a solucionar mi problema, no funcionó para todos los archivos en un subdirectorio. También usé en Content Includelugar de 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
Cada otra permutación de todas las otras respuestas / sugerencias no funcionó para mí. Ni siquiera una mención del archivo en la salida de compilación detallada. Pero tu sugerencia aquí funcionó.
user7817808

15
Y si desea incluir subcarpetas intermedias, use<Content Include="layouts\**\*.*">
JSancho

3
Cuando use el Web SDK ( <Project Sdk="Microsoft.NET.Sdk.Web">), no le permitirá usarlo Include=porque ya parece especificarlo implícitamente dentro del SDK. Tuve que usarlo Update=para construir e incluir mis archivos adicionales.
notracs

Bien, gracias .. Pero cómo copiar solo el contenido de la carpeta al directorio de salida, no a la carpeta en sí. La expresión assets\*.*debe asumirlo. Pero copia la carpeta de activos completa. Así que tengo bin/Debug/netcoreapp3.1/assets/...Pero quiero los archivos de la carpeta de activos en el directorio raíz de la salida. bin/Debug/netcoreapp3.1/....
Dominik

Encontré una solución: 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> (vea mi respuesta para un mejor formato de código).
Dominik

15

Coloque esto en su archivo .csproj reemplazando nlog.config con la ruta de archivo deseada. Luego, simplemente guárdelo y construya su proyecto:

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

Esto no parece copiar subdirectorios.
nulo

13

Suponiendo que tiene una assetscarpeta en su directorio raíz. Puedes nombrarlo como quieras. Este es solo un ejemplo:

tu-proyecto.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>

esto copia solo el contenido de la assetscarpeta en la raíz de salida sin envolverlo en la assetscarpeta. Pero si desea copiar con la carpeta en sí, puede usar el siguiente código:

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

3

Tenía el requisito de que una selección de plantillas HTML fueran consumibles tanto del lado del cliente como del lado del servidor (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

Gracias por salvarme el día, si necesita forzar la copia de un paquete nuget específico en un proyecto principal de asp.net (2.2), agregue al final de su 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
Lo ideal es utilizar una tarea <Copy> para que sea multiplataforma.
Bruno García
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.