在.csproj 中包含项目锥体外部的内容文件

我有一个 C # 项目,名为 MyProject.csproj,位于“ C: Projects MyProject”。我也有文件,我想复制到这个项目的输出目录。但是,这些文件位于“ C: MyContentFiles”的位置,也就是说,它们不在项目锥体内。这个目录也有子目录。不管理目录的内容。因此,我必须包括所有的下面是什么。

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

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

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

117591 次浏览

You need to add file as a link:

  1. Right click on the project in VS.
  2. Add -> Existing Item...
  3. Find the file.
  4. Select it and.
  5. Add as a Link (drop down in the Add Button in the dialog).
  6. Open the properties of the file and set "Copy to Output Directory" to "Copy always".

BUT You cannot do it for the directory tree.
Instead you need to write post-build task for that. This is a sample that will get you stared.

The following, which you would add to the bottom of your project file, will copy your content files maintaining the directory structure in a after build event to the target directory $(TargetDirectory) of your build (typically $(MSBuildProjectDirectory)\bin\Debug ).

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


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

If these files needed to go in a directory named MyContentFiles, you could add this before the copy:

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

and change

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

To

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

I believe @Dmytrii gets it right on one hand - you want to use the "link" feature.

However, he's only partly correct when saying you can't link to a directory tree. While this is, indeed, true when trying to add the links using Visual Studio's GUI, MSBuild supports this.

If you want to preserve the directory structure, just add the %(RecursiveDir) tag to your <link> node:

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

The page MSBuild Well-known Item Metadata goes into more detail on the metadata you can access.

The answer of Mandark adds the content files directly to the solution, and they will show up in the solution explorer. Whenever a file is added or deleted in the original directory, this is not picked up by visual studio automatically. Also, whenever a file is deleted or added in the solution explorer, the project file is altered, and all files are included separately, instead of just including the folder.

To prevent this, you can use the same trick, but put it in a separate project file and then import it.

The project file (for example include.proj) looks like this:

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

In your own project file, add the following line

<Import Project="include.proj" />

Visual Studio will not mess with this file, and just adds files as content during a build. Changes in the original directory are always included. The files won't show up in your solution explorer, but will be included in the output directory.

Picked up on this trick here: http://blogs.msdn.com/b/shawnhar/archive/2007/06/06/wildcard-content-using-msbuild.aspx

I think

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

Is just enough, since you want everything in that folder and subfolders

To ignore a file in a .Net Core project:

<ItemGroup>
<Content Include="appsettings.local.json">
<CopyToOutputDirectory Condition="Exists('appsettings.local.json')">PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

To include files in a folder for a .NET Core project,

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

And the items' property "Copy to Output Directory" will be "Copy if newer":
Copy if newer