97

我有一个 C# 项目说 MyProject.csproj 位于“C:\Projects\MyProject\”。我还有一些文件要复制到该项目的输出目录中。但是,文件位于“C:\MyContentFiles\”位置,即它们不在项目锥内。该目录也有子目录。目录的内容不受管理。因此,我必须包括它下面的所有内容。

当我将它们作为“内容”包含在项目中时,它们会被复制,但目录结构会丢失。我做了这样的事情: -

<Content Include="..\..\MyContentFiles\**">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

如何在保留目录结构的情况下将这些文件/目录递归复制到项目的输出目录中?

4

7 回答 7

180

我相信@Dmytrii一方面是正确的——你想使用“链接”功能。

然而,当他说你不能链接到目录树时,他只是部分正确。虽然在尝试使用 Visual Studio 的 GUI 添加链接时确实如此,但 MSBuild 支持这一点。

如果要保留目录结构,只需将%(RecursiveDir)标签添加到您的<link>节点:

<Content Include="..\..\MyContentFiles\**\*.*">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

MSBuild Well-known Item Metadata页面更详细地介绍了您可以访问的元数据。

于 2012-08-04T13:05:30.123 回答
60

您需要将文件添加为链接:

  1. 右键单击VS中的项目。
  2. 添加 -> 现有项目...
  3. 找到文件。
  4. 选择它和。
  5. 添加为链接(在对话框的添加按钮中下拉)。
  6. 打开文件的属性并将“复制到输出目录”设置为“始终复制”。

但是您不能为目录树执行此操作。
相反,您需要为此编写构建后任务。这是一个让你目瞪口呆的样本。

于 2009-08-18T07:41:17.257 回答
31

Mandark的答案直接将内容文件添加到解决方案中,它们将显示在解决方案资源管理器中。每当在原始目录中添加或删除文件时,Visual Studio 不会自动获取该文件。此外,每当在解决方案资源管理器中删除或添加文件时,项目文件都会更改,并且所有文件都单独包含,而不仅仅是包含文件夹。

为了防止这种情况,您可以使用相同的技巧,但将其放在单独的项目文件中,然后将其导入。

项目文件(例如 include.proj)如下所示:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="..\..\MyContentFiles\**">
  <Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

在您自己的项目文件中,添加以下行

<Import Project="include.proj" />

Visual Studio 不会弄乱这个文件,只是在构建过程中添加文件作为内容。始终包括原始目录中的更改。这些文件不会显示在您的解决方案资源管理器中,但会包含在输出目录中。

在这里学到了这个技巧:http: //blogs.msdn.com/b/shawnhar/archive/2007/06/06/wildcard-content-using-msbuild.aspx

于 2014-10-05T22:57:36.280 回答
13

您将添加到项目文件底部的以下内容将在构建后事件中将维护目录结构的内容文件复制到构建的目标目录$(TargetDirectory)(通常是$(MSBuildProjectDirectory)\bin\Debug.

<ItemGroup>
    <ExtraContent Include="$(MSBuildProjectDirectory)\..\..\MyContentFiles\**" />
</ItemGroup>

<Target Name="AfterBuild">
    <Copy 
        SourceFiles="@(ExtraContent)" 
        DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
        SkipUnchangedFiles="true" />
</Target>

如果这些文件需要放在名为 MyContentFiles 的目录中,您可以在副本之前添加:

<MakeDir Directories="$(TargetDir)\MyContentFiles" Condition=" !Exists('$(TargetDir\MyContentFiles') " />

和改变

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />

<Copy 
            SourceFiles="@(ExtraContent)" 
            DestinationFiles="@(ExtraContent->'$(TargetDir)\MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)')" 
            SkipUnchangedFiles="true" />
于 2009-08-20T02:47:12.467 回答
5

我认为

<Content Include="..\..\MyContentFiles\**\*.*">
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

就足够了,因为您想要该文件夹和子文件夹中的所有内容

于 2014-10-21T14:48:34.440 回答
4

要在 .NET Core 项目的文件夹中包含文件,

<!--Just files-->
<ItemGroup>
  <None Update="..\..\MyContentFiles\**\*.*">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>
<!--Content files-->
<ItemGroup>
  <Content Include="..\..\MyContentFiles\**\*.*" Link="MyContentFiles\%(RecursiveDir)%(Filename)%(Extension)">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

并且项目的属性“复制到输出目录”将是“如果更新则复制”:
如果较新,请复制

于 2018-10-24T12:58:21.823 回答
-1

要忽略 .Net Core 项目中的文件:

<ItemGroup>
 <Content Include="appsettings.local.json">
   <CopyToOutputDirectory Condition="Exists('appsettings.local.json')">PreserveNewest</CopyToOutputDirectory>
 </Content>
</ItemGroup>
于 2018-07-10T07:52:02.270 回答