简体   繁体   中英

csproj include (recursive) folders based on a list (batching)

I want to add some files recursively to a single project that are located in folders inside my solution root.

Right now, I found a working solution to add those files by specifying each folder manually:

  <ItemGroup>
    <Content Include="..\Folder1\**\*">
        <Link>Folder1\%(RecursiveDir)\%(Filename)%(Extension)</Link>
    </Content>
    <Content Include="..\Folder2\**\*">
        <Link>Folder2\%(RecursiveDir)\%(Filename)%(Extension)</Link>
    </Content>
    <Content Include="..\Folder3\**\*">
        <Link>Folder3\%(RecursiveDir)\%(Filename)%(Extension)</Link>
    </Content>
  </ItemGroup>

As those can be a handfull folders and they can be different depending on my solution, I want to have an easy list to define the folder names.

Something like this:

  <PropertyGroup>
    <DefinedResourceFolders>Folder1;Folder2;Folder3</DefinedResourceFolders>
  </PropertyGroup>

This would also allow me to input this as a property directly when calling msbuild to extend the files that are going to the build output, maybe.
I tried to look into the MSBuild Batching documentation and several other online sources, but I could not figure it out. Most batching examples I found were working with Targets, not Includes into the solution items.

Is this possible? How would I define the <ItemGroup> for the content then?


PS: I don't care about wildcard issues with .csproj files when new files are added, etc. This will either be a single "Resources" project only containing those displayed files, or I am using my external .props file that I am importing into each .csproj file anyway.

Suppose you want to include all files in folders root/Folder1 , root/Folder2 and root/Folder3 recursively.

This is how the builds (both VS and CLI) do what you want. However, VS will not show the files as part of the project.

<Project Sdk="Microsoft.NET.Sdk" InitialTargets="__AddBatchedContent;$(InitialTargets)">
  <!-- the usual properties -->

  <!-- You could of course define the folder array directly in an Item,
       but this is what you wanted :-) -->
  <PropertyGroup>
    <Lookups>Folder1;Folder2;Folder3</Lookups>
  </PropertyGroup>
  <ItemGroup>
    <LookupDir Include="$(Lookups)" />
  </ItemGroup>

  <Target Name="__AddBatchedContent">
    <ItemGroup>
      <!-- save the original source folder of the globbed file name in custom
           metadata "Folder" so we can use it later as its output base folder -->
      <__BatchedFiles Include="..\%(LookupDir.Identity)\**\*" Folder="%(LookupDir.Identity)" />
      <Content Include="@(__BatchedFiles)" Link="%(Folder)\%(RecursiveDir)\%(Filename)%(Extension)" CopyToOutputDirectory="Always" />
    </ItemGroup>
  </Target>

</Project>

Note that if you want to put this in a.targets file to use this technique in multiple projects, you should replace the ..\ with $(MSBuildThisFileDirectory)..\ so that the path is relative to the (known) location of the.targets file instead of the (unknown) location of the importing project.

Thanks to @Ilya Kozhevnikov for the basis of this answer .

You are not the only one who would like this to be simpler:-): https://github.com/do.net/msbuild/issues/3274

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM