我有一个脚本尝试从某个目录中的所有文件中构造ItemGroup
,同时排除具有特定名称的文件(无论扩展名如何)。
最初要排除的文件列表包含文件扩展名,我使用社区任务“RegexReplace
将星号替换为星号”。然后,我在项目的Exclude
属性中使用此列表。由于某种原因,即使列表显示正确,也不会正确排除文件。
为了找到原因,我创建了一个测试脚本(下面),它有两个任务:第一个用两种不同的方式初始化两个带有文件模式列表的属性。第二个任务打印属性和在Exclude
属性中使用这两个属性产生的文件。
属性的值看起来是相同的,但结果组是不同的。这怎么可能?
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Init;Test" ToolsVersion="3.5">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<Target Name="Init">
<ItemGroup>
<OriginalFilenames Include="TestDir\SampleProj.exe"/>
<OriginalFilenames Include="TestDir\SampleLib1.dll"/>
</ItemGroup>
<RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*">
<Output TaskParameter="Output" ItemName="PatternedFilenames"/>
</RegexReplace>
<PropertyGroup>
<ExcludeFilesA>TestDir\SampleProj.*;TestDir\SampleLib1.*</ExcludeFilesA>
<ExcludeFilesB>@(PatternedFilenames)</ExcludeFilesB>
</PropertyGroup>
</Target>
<Target Name="Test">
<Message Text='ExcludeFilesA: $(ExcludeFilesA)' />
<Message Text='ExcludeFilesB: $(ExcludeFilesB)' />
<ItemGroup>
<AllFiles Include="TestDir\**"/>
<RemainingFilesA Include="TestDir\**" Exclude="$(ExcludeFilesA)"/>
<RemainingFilesB Include="TestDir\**" Exclude="$(ExcludeFilesB)"/>
</ItemGroup>
<Message Text="
**AllFiles**
@(AllFiles, '
')" />
<Message Text="
**PatternedFilenames**
@(PatternedFilenames, '
')" />
<Message Text="
**RemainingFilesA**
@(RemainingFilesA, '
')" />
<Message Text="
**RemainingFilesB**
@(RemainingFilesB, '
')" />
</Target>
</Project>
输出(为了清晰起见,稍微重新格式化):
ExcludeFilesA: TestDir\SampleProj.*;TestDir\SampleLib1.*
ExcludeFilesB: TestDir\SampleProj.*;TestDir\SampleLib1.*
AllFiles:
TestDir\SampleLib1.dll
TestDir\SampleLib1.pdb
TestDir\SampleLib2.dll
TestDir\SampleLib2.pdb
TestDir\SampleProj.exe
TestDir\SampleProj.pdb
PatternedFilenames:
TestDir\SampleProj.*
TestDir\SampleLib1.*
RemainingFilesA:
TestDir\SampleLib2.dll
TestDir\SampleLib2.pdb
RemainingFilesB:
TestDir\SampleLib1.dll
TestDir\SampleLib1.pdb
TestDir\SampleLib2.dll
TestDir\SampleLib2.pdb
TestDir\SampleProj.exe
TestDir\SampleProj.pdb
观察ExcludeFilesA
和ExcludeFilesB
看起来相同,但结果组RemainingFilesA
和RemainingFilesB
不同。
最终,我希望使用生成RemainingFilesA
的方式生成的模式获取列表ExcludeFilesB
。你能提出一个方法,还是我必须彻底重新考虑我的做法?
答案 0 :(得分:2)
当自定义任务引发异常时,意外泄露了这个原因。
ExcludeFilesA
的实际值是TestDir\SampleProj.*;TestDir\SampleLib1.*
,就像人们所期望的那样。但是,ExcludeFilesB
的实际值为TestDir\SampleProj.%2a;TestDir\SampleLib1.%2a
。
大概Message
在使用之前对字符串进行取景,但Include
和Exclude
没有。这可以解释为什么字符串看起来相同但表现不同。
顺便说一句,执行顺序似乎与此无关,我很确定(经过大量实验)所有内容都按照它在此脚本中出现的顺序执行和评估。< / p>
答案 1 :(得分:0)
在目标执行之前需要评估ItemGroups,并且在其目标容器中动态创建PatternedFilenames
ItemGroup。
您可以使用CreateItem任务解决此问题,这将确保整个执行期间的PatternedFilenames
范围:
<RegexReplace Input="@(OriginalFilenames)" Expression="\.\w+$" Replacement=".*">
<Output TaskParameter="Output" ItemName="PatternedFilenames_tmp"/>
</RegexReplace>
<CreateItem Include="@(PatternedFilenames_tmp)">
<Output TaskParameter="Include" ItemName="PatternedFilenames"/>
</CreateItem>