使用csproj dotnetcore将文件复制到输出目录

188

我的问题非常简单。我有一些文件,希望无论是调试构建还是发布版本,在构建输出目录中都能将它们复制过去。所有我找到的信息都是关于旧的json配置方法的。请问是否有使用dotnetcore的csproj示例?

9个回答

240

根据您的需求,有很多方法可以实现您的目标。

最简单的方法是有条件地设置元数据 (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 属性:

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

这个条件(Condition)属性可以应用于<Target>元素或类似<Copy>的任务元素。


1
我该如何将“DestinationFolder”应用于<Reference>项,或者是否可能这样做?我在文档中找不到太多信息。我不想所有程序集都在根目录下,而是希望它们能够在自己的文件夹中。 - Reahreic
您可以直接在Reference项上设置DestinationSubDirectory="subdir\"元数据。但是这意味着您需要自己实现程序集解析(AssemblyResolve事件)。 - Martin Ullrich
1
我该如何复制包含某些dll文件的父文件夹到相应的文件夹中?我想将它们置于输出发布路径中,以便在构建完成后这些文件夹在应用程序运行时可用,因为我在启动时作为插件加载这些dll文件。我正在 Mac 上使用 Rider。 - kuldeep
警告:如果您正在使用Azure Pipelines,并且要复制的文件除了在同一.csproj文件中的PreBuild步骤之外不存在。您将遇到一个鸡生蛋的问题,其中构建代理“错过”文件。这可能与构建步骤期间提供的警告有关:https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops#troubleshooting - Nathan Goings

161

虽然这帮助我解决了我的问题,但它并没有对子目录中的所有文件起作用。我还使用了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
30
如果您想包含中间子文件夹,请使用 <Content Include="layouts\**\*.*"> - JSancho
4
在使用Web SDK (<Project Sdk="Microsoft.NET.Sdk.Web">)时,不能使用 Include=,因为它似乎已经在SDK中隐含地指定了它。我不得不使用Update=来构建并包含我的其他文件。 - notracs
1
好的,谢谢。但是如何仅复制文件夹的内容到输出目录而不是文件夹本身呢?表达式assets\*.*应该可以做到这一点。但它会复制整个assets文件夹。所以我有了bin/Debug/netcoreapp3.1/assets/...,但我想要将assets文件夹中的文件复制到输出的根目录中。bin/Debug/netcoreapp3.1/... - Domske
2
我找到了一个解决方案: (请查看我的答案以获取更好的代码格式。) - Domske
不确定为什么,但我不得不使用<None Update="layouts\*.*>才能让我的工作正常。 - nedstark179

47
假设您的根目录中有一个名为assets的文件夹,您可以根据需要命名。这只是一个示例: 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>

这个代码将只复制 assets 文件夹的内容到输出目录,而不会将其包装为 assets 文件夹。但如果你想连同文件夹一起复制,可以使用以下代码:

这段代码会将整个 assets 文件夹及其内容复制到输出目录:

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

2
太棒了,我正需要assets***.*这个东西...两个通配符可以指定深度。谢谢! - Vedran Mandić

18

将此代码放置在您的.csproj文件中,将nlog.config替换为所需的文件路径。然后保存并构建您的项目:

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

这似乎无法复制子目录。 - null

8

我需要一些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>

7
例如,你有一个名为test.txt的文件。要将总是复制设置为此文件,您需要将以下内容添加到您的.csproj文件中:
<ItemGroup>
    <None Include="test.txt">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
</ItemGroup>

5
这将会复制整个目录到子目录中,并使用正确的名称。
<ItemGroup>
    <Content 
      Include="..\libs\x64\**\*.*"
      CopyToOutputDirectory="Always"
      TargetPath="x64\%(Filename)%(Extension)"
    />
</ItemGroup>

2
如果您需要强制将特定的NuGet包复制到ASP.NET Core项目(2.2)中,请在csproj末尾添加以下内容:

最初的回答:

<ItemGroup>
    <PackageReference Include="PackageName" Version="PackageVersion" />
</ItemGroup>

<!-- 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>

或者

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

5
最好使用 <Copy> 任务使其跨平台。 - Bruno Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接