获取msbuild中的子目录列表

获取msbuild中的子目录列表,msbuild,subdirectory,Msbuild,Subdirectory,给定目录列表: <ItemGroup> <Dirs Include="Foo\Dir1" /> <Dirs Include="Foo\Dir2" /> </ItemGroup> 但我想知道是否有更简单的方法。摘自《MSBuild诡计》一书: 您需要首先启用扩展属性函数集,方法是确保环境变量MSBuildEnableAllPropertyFunctions设置为值1(这是导入的.tasks文件通过内联任务完成的) 设置@(Dirs)后,

给定目录列表:

<ItemGroup>
  <Dirs Include="Foo\Dir1" />
  <Dirs Include="Foo\Dir2" />
</ItemGroup>
但我想知道是否有更简单的方法。

摘自《MSBuild诡计》一书:


您需要首先启用扩展属性函数集,方法是确保环境变量MSBuildEnableAllPropertyFunctions设置为值1(这是导入的.tasks文件通过内联任务完成的)

设置@(Dirs)后,可以使用Remove属性对其进行过滤,以除去Subversion文件夹。


<CreateItem Include="$(OutputFolder)\*\*.*">
  <Output TaskParameter="Include" ItemName="FilesInSubFolders" />
</CreateItem>

<RemoveDuplicates Inputs="@(FilesInSubFolders->'%(RelativeDir)')">
  <Output TaskParameter="Filtered" ItemName="SubDirs"/>
</RemoveDuplicates>

<Message Text="@(SubDirs)"/>

这将把所有直接子文件夹路径放入@(子文件夹)。如果您将
Include=“$(OutputFolder)\*\*.*”
更改为
Include=“$(OutputFolder)\***.*”
,它将递归地包括所有子文件夹。

用一个完全独立的示例来扩展Brian的答案:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GetSubdirectories">
  <UsingTask TaskName="SetEnvironmentVariable"
             TaskFactory="CodeTaskFactory"
             AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
    <ParameterGroup>
      <Name ParameterType="System.String" Required="true" />
      <Value ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs"><![CDATA[
        Environment.SetEnvironmentVariable(Name, Value);
      ]]></Code>
    </Task>
  </UsingTask>

  <Target Name="GetSubdirectories">
    <SetEnvironmentVariable Name="MSBuildEnableAllPropertyFunctions" Value="1" />
    <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::EnumerateFiles('.\Stuff', '*', System.IO.SearchOption.AllDirectories))"/>
    </ItemGroup>
    <Message Text="%(Dirs.Identity)" />
  </Target>
</Project>



我从中获得了UsingTask示例。

我假设内联任务将调用
环境.SetEnvironmentVariable
,但谁调用该任务?此外,如果您将该文件计算在内,它甚至比我的示例中的代码还要多:)任务将在导入中使用InitialTargets声明自动运行。诚然,它确实添加了一些代码行,但它们被添加到可重用的导入文件中,该文件扩展了整个可用属性函数集,因此,如果您的构建需要任何其他扩展,您就可以准备好了。这不是一个很大的进步,但也许是朝着正确的方向迈出的一步?(本书对此进行了深入探讨)
<CreateItem Include="$(OutputFolder)\*\*.*">
  <Output TaskParameter="Include" ItemName="FilesInSubFolders" />
</CreateItem>

<RemoveDuplicates Inputs="@(FilesInSubFolders->'%(RelativeDir)')">
  <Output TaskParameter="Filtered" ItemName="SubDirs"/>
</RemoveDuplicates>

<Message Text="@(SubDirs)"/>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="GetSubdirectories">
  <UsingTask TaskName="SetEnvironmentVariable"
             TaskFactory="CodeTaskFactory"
             AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
    <ParameterGroup>
      <Name ParameterType="System.String" Required="true" />
      <Value ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Code Type="Fragment" Language="cs"><![CDATA[
        Environment.SetEnvironmentVariable(Name, Value);
      ]]></Code>
    </Task>
  </UsingTask>

  <Target Name="GetSubdirectories">
    <SetEnvironmentVariable Name="MSBuildEnableAllPropertyFunctions" Value="1" />
    <ItemGroup>
      <Dirs Include="$([System.IO.Directory]::EnumerateFiles('.\Stuff', '*', System.IO.SearchOption.AllDirectories))"/>
    </ItemGroup>
    <Message Text="%(Dirs.Identity)" />
  </Target>
</Project>