MSBuild ItemGroup包含/排除模式问题

MSBuild ItemGroup包含/排除模式问题,msbuild,itemgroup,Msbuild,Itemgroup,问题:无法根据exclude属性中传递的值正确生成ItemGroups数组 如果运行此脚本,它将创建一些示例文件,然后尝试基于Include/Exclude属性创建一个名为files的数组,问题是当Exclude不是硬编码或非常简单的属性时,它会出错 目标DynamicExcludeList错误地选择了这些文件: .\a文件夹\test.cs\AFolder\test.txt 目标HardcodexCludelist正确选择这些文件: \a文件夹\test.txt 非常感谢任何帮助,这让我发疯。

问题:无法根据exclude属性中传递的值正确生成ItemGroups数组

如果运行此脚本,它将创建一些示例文件,然后尝试基于Include/Exclude属性创建一个名为files的数组,问题是当Exclude不是硬编码或非常简单的属性时,它会出错

目标DynamicExcludeList错误地选择了这些文件:
.\a文件夹\test.cs\AFolder\test.txt

目标HardcodexCludelist正确选择这些文件:
\a文件夹\test.txt

非常感谢任何帮助,这让我发疯。

(请注意其msbuild v4)


.\DIRECTORY\u NAME\u TOKEN\***.cs
$(CommonFileExclution.Replace('DIRECTORY\u NAME\u TOKEN','AFolder'))
.\a文件夹\***\.cs
这是输出,请注意“文件”和“文件硬编码包含”之间的区别

PS C:\SVN\TrunkDeployment\TestMsBuild> msbuild .\Test.build.xml Microsoft (R) Build Engine Version 4.0.30319.1 [Microsoft .NET Framework, Version 4.0.30319.1] Copyright (C) Microsoft Corporation 2007. All rights reserved. Build started 8/10/2010 2:30:42 PM. Project "C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml" on node 1 (default targets). DynamicExcludeList: FinalExcludes: .\AFolder\**\*.cs TheFiles: .\AFolder\test.cs;.\AFolder\test.txt HardcodedExcludeList: FinalExcludes: .\AFolder\**\*.cs TheFilesWithHardcodedExcludes: .\AFolder\test.txt Done Building Project "C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml" (default targets). Build succeeded. 0 Warning(s) 0 Error(s) Time Elapsed 00:00:00.06 PS C:\SVN\TrunkDeployment\TestMsBuild>msbuild。\Test.build.xml Microsoft(R)生成引擎版本4.0.30319.1 [Microsoft.NET Framework,版本4.0.30319.1] 版权所有(C)微软公司2007。版权所有。 构建开始于2010年8月10日下午2:30:42。 节点1上的项目“C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml”(默认目标)。 动态排除列表: 最终结果包括:.\a文件夹\***.cs 文件:。\AFolder\test.cs\AFolder\test.txt 硬代码目录: 最终结果包括:.\a文件夹\***.cs 文件硬编码索引包括:。\AFolder\test.txt 已完成生成项目“C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml”(默认目标)。 构建成功。 0个警告 0个错误 时间流逝00:00:00.06 编辑

我已经更新了上面的脚本以使用CreateItem,但是当要排除的项目列表包含多个路径时仍然存在问题(即,CommonFileExclution的值已更改):


.\DIRECTORY\u NAME\u TOKEN\***.cs\目录\u NAME\u TOKEN\***.vb;
$(CommonFileExclution.Replace('DIRECTORY\u NAME\u TOKEN','AFolder'))
.\a文件夹\***\.cs\A文件夹\***\.vb

在target
DynamicExcludeList
中,使用
CreateItem
任务而不是
ItemGroup
动态生成项目:

<Target Name="DynamicExcludeList" >

  <PropertyGroup>
    <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs</CommonFileExclusion>
    <FinalExcludes>$(CommonFileExclusion.Replace('DIRECTORY_NAME_TOKEN', 'AFolder'))</FinalExcludes>
  </PropertyGroup>

  <Message Text="FinalExcludes: $(FinalExcludes)" />

  <CreateItem Include=".\AFolder\**\*;"
              Exclude="$(FinalExcludes)">
    <Output TaskParameter="Include" ItemName="TheFiles"/>
  </CreateItem>

  <Message Text="TheFiles: @(TheFiles)" />
</Target>

.\DIRECTORY\u NAME\u TOKEN\***.cs
$(CommonFileExclution.Replace('DIRECTORY\u NAME\u TOKEN','AFolder'))

理论上,
ItemGroup
CreateItem
是等效的,但我见过这样的情况(动态情况),当必须使用
CreateItem

好的,我试了一下,我认为问题是因为您使用了一个属性来表示多个值的标量值。我建议进行批处理和转换(请参阅和)。例如,以下代码正在工作:

<Target Name="DynamicExcludeList" >
  <ItemGroup>
    <ExtensionsExcluded Include="cs;vb" />
  </ItemGroup>

  <CreateItem Include=".\AFolder\**\*"
          Exclude="@(ExtensionsExcluded->'.\AFolder\**\*.%(identity)')">
    <Output TaskParameter="Include" ItemName="TheFiles"/>
  </CreateItem>
  <Message Text="TheFiles: @(TheFiles)" />
</Target>


事实上,在解析脚本时,在运行每个目标之前,都会对属性和项目组进行评估。这就是为什么项目组没有填充您的想法,而是填充执行msbuild脚本之前的内容。你可以在这里阅读更多关于它的信息:和。避免此问题的一个好方法是在目标之外使用ItemGroup(对于静态项)和在内部使用createitem(对于动态项),感谢您的解释。但是,如果您查看有关CreateItem()的文档,您会发现此任务已被弃用,因此您可能会认为目标中的ItemGroup将像CreateItem一样进行动态计算。感谢您的反馈,我仍然有一个问题(稍后发布),如下所示:,CreateItem在3.5中已过时CreateItem自.NET 3.5以来已被弃用,但您仍可以使用它。它解决了您的问题在我的初始示例中解决了这个问题,为了简单起见,我开始实施您的修复,但在我为CommonFileExclution的价值添加了更多路径后遇到了相同的问题,如果您仍然有任何想法的话,这将是非常棒的(我更新了我的帖子,上面提到了这个问题)。感谢您的帮助谢谢您的修复,这只是MSBuild(IMO)中令人讨厌的事情之一,因为它变得越来越复杂,您希望添加的排除项越多(例如,某些目录中的某些文件,但其他目录中的文件除外),您可能会寻找其他解决方案。
<Target Name="DynamicExcludeList" >

  <PropertyGroup>
    <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs</CommonFileExclusion>
    <FinalExcludes>$(CommonFileExclusion.Replace('DIRECTORY_NAME_TOKEN', 'AFolder'))</FinalExcludes>
  </PropertyGroup>

  <Message Text="FinalExcludes: $(FinalExcludes)" />

  <CreateItem Include=".\AFolder\**\*;"
              Exclude="$(FinalExcludes)">
    <Output TaskParameter="Include" ItemName="TheFiles"/>
  </CreateItem>

  <Message Text="TheFiles: @(TheFiles)" />
</Target>
<Target Name="DynamicExcludeList" >
  <ItemGroup>
    <ExtensionsExcluded Include="cs;vb" />
  </ItemGroup>

  <CreateItem Include=".\AFolder\**\*"
          Exclude="@(ExtensionsExcluded->'.\AFolder\**\*.%(identity)')">
    <Output TaskParameter="Include" ItemName="TheFiles"/>
  </CreateItem>
  <Message Text="TheFiles: @(TheFiles)" />
</Target>