11

问题:没有根据 exclude 属性中传递的值正确构建 ItemGroups 数组。

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

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

目标 HardcodedExcludeList 正确选择了这些文件:
.\AFolder\test.txt

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

(注意它的 msbuild v4)

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run">

      <Target Name="Run" >
        <CallTarget Targets="CreateSampleFiles" />
        <CallTarget Targets="DynamicExcludeList" />
        <CallTarget Targets="HardcodedExcludeList" />
      </Target>

      <Target Name="CreateSampleFiles" >
        <MakeDir Directories="AFolder" />
        <WriteLinesToFile Lines="Test" File="AFolder\test.cs" Overwrite="true" />
        <WriteLinesToFile Lines="Test" File="AFolder\test.txt" Overwrite="true" />
      </Target>

      <Target Name="DynamicExcludeList" >

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

        <Message Text="FinalExcludes: $(FinalExcludes)" />
        <ItemGroup>
          <TheFiles 
            Include=".\AFolder\**\*;" 
            Exclude="$(FinalExcludes)"
          />
        </ItemGroup>
        <Message Text="TheFiles: @(TheFiles)" />

      </Target>

      <Target Name="HardcodedExcludeList" >

        <PropertyGroup>
          <FinalExcludes>.\AFolder\**\*.cs</FinalExcludes>
        </PropertyGroup>

        <Message Text="FinalExcludes: $(FinalExcludes)" />
        <ItemGroup>
          <TheFilesWithHardcodedExcludes
            Include=".\AFolder\**\*;"
            Exclude="$(FinalExcludes)"
          />
        </ItemGroup>
        <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" />

      </Target>  
    </Project>

这是输出,请注意“TheFiles”和“TheFilesWithHardcodedExcludes”之间的区别

PS C:\SVN\TrunkDeployment\TestMsBuild> msbuild .\Test.build.xml
Microsoft (R) Build Engine 版本 4.0.30319.1
[Microsoft .NET 框架,版本 4.0.30319.1]
版权所有 (C) Microsoft Corporation 2007。保留所有权利。

构建于 2010 年 8 月 10 日下午 2:30:42 开始。
节点 1 上的项目“C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml”(默认目标)。
动态排除列表:
  FinalExcludes: .\AFolder\**\*.cs
  文件:.\AFolder\test.cs;.\AFolder\test.txt
硬编码排除列表:
  FinalExcludes: .\AFolder\**\*.cs
  TheFilesWithHardcodedExcludes: .\AFolder\test.txt
完成构建项目“C:\SVN\TrunkDeployment\TestMsBuild\Test.build.xml”(默认目标)。


构建成功。
    0 个警告
    0 错误

经过时间 00:00:00.06

编辑

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

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Run">

      <Target Name="Run" >
        <CallTarget Targets="CreateSampleFiles" />
        <CallTarget Targets="DynamicExcludeList" />
        <CallTarget Targets="HardcodedExcludeList" />
      </Target>

      <Target Name="CreateSampleFiles" >
        <MakeDir Directories="AFolder" />
        <WriteLinesToFile Lines="Test" File="AFolder\test.cs" Overwrite="true" />
        <WriteLinesToFile Lines="Test" File="AFolder\test.txt" Overwrite="true" />
        <WriteLinesToFile Lines="Test" File="AFolder\test.vb" Overwrite="true" />
      </Target>

      <Target Name="DynamicExcludeList" >

        <PropertyGroup>
          <CommonFileExclusion>.\DIRECTORY_NAME_TOKEN\**\*.cs;.\DIRECTORY_NAME_TOKEN\**\*.vb;</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="HardcodedExcludeList" >

        <PropertyGroup>
          <FinalExcludes>.\AFolder\**\*.cs;.\AFolder\**\*.vb</FinalExcludes>
        </PropertyGroup>

        <Message Text="FinalExcludes: $(FinalExcludes)" />
        <CreateItem Include=".\AFolder\**\*;"
                     Exclude="$(FinalExcludes)">
          <Output TaskParameter="Include" ItemName="TheFilesWithHardcodedExcludes"/>
        </CreateItem>
        <Message Text="TheFilesWithHardcodedExcludes: @(TheFilesWithHardcodedExcludes)" />

      </Target>
    </Project>
4

2 回答 2

19

好的,我尝试了一点,我认为问题出在您使用代表多个值的 SCALAR 值的属性这一事实。我建议进行批处理和转换(请参阅http://scottlaw.knot.org/blog/?p=402http://msdn.microsoft.com/en-us/library/ms171476.aspx)。例如,以下代码正在运行:

<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>
于 2010-10-08T15:54:56.857 回答
2

在目标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>

理论上是等价的ItemGroupCreateItem但我见过这样的情况(动态情况)CreateItem必须使用。

于 2010-10-08T13:46:18.460 回答