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