在MSBuild中,如何聚合ItemGroup(具体来说,找到组中元数据中的最大数字?)

时间:2017-10-31 20:57:10

标签: msbuild

我尝试使用批处理目标按包含数字的元数据字段进行批处理:

<?xml version="1.0" encoding="utf-8"?>

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

  <PropertyGroup>
    <HighestNumber>0</HighestNumber>
  </PropertyGroup>

  <ItemGroup>
    <TextFiles Include="*.txt" />
    <TextFiles Update="*.txt">
      <Number>%(TextFiles.Filename)</Number>
    </TextFiles>
  </ItemGroup>

  <Target Name="SetUpMyStuff">
    <Message Importance="High" Text="HighestNumber: $(HighestNumber)"/>
    <CallTarget Targets="FindLargerNumber" />
    <Message Importance="High" Text="HighestNumber: $(HighestNumber)"/>
  </Target>

  <Target Name="FindLargerNumber">
    <CreateProperty Value="$([System.Math]::Max($(HighestNumber), %(TextFiles.Number)))">
      <Output PropertyName="HighestNumber" TaskParameter="ValueSetByTask" />
    </CreateProperty>
    <Message Importance="High" Text="HighestNumber: $(HighestNumber)"/>
  </Target>

</Project>

这是诊断输出:

1>  Using "Message" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
1>  Task "Message"
1>    Task Parameter:Importance=High
1>    Task Parameter:Text=HighestNumber: 0
1>    HighestNumber: 0
1>  Done executing task "Message".
1>  Using "CallTarget" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
1>  Task "CallTarget"
1>    Task Parameter:Targets=FindLargerNumber
1>    Target "FindLargerNumber" in file "e:\Projects\BaseLibrary\Test.targets":
1>      Using "CreateProperty" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
1>      Task "CreateProperty"
1>        Task Parameter:Value=0
1>        Output Property: HighestNumber=0
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=1
1>        Output Property: HighestNumber=1
1>        The property "HighestNumber" with value "0" is being overridden by another batch. The property is now: "1"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=10
1>        Output Property: HighestNumber=10
1>        The property "HighestNumber" with value "1" is being overridden by another batch. The property is now: "10"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=2
1>        Output Property: HighestNumber=2
1>        The property "HighestNumber" with value "10" is being overridden by another batch. The property is now: "2"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=3
1>        Output Property: HighestNumber=3
1>        The property "HighestNumber" with value "2" is being overridden by another batch. The property is now: "3"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=4
1>        Output Property: HighestNumber=4
1>        The property "HighestNumber" with value "3" is being overridden by another batch. The property is now: "4"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=5
1>        Output Property: HighestNumber=5
1>        The property "HighestNumber" with value "4" is being overridden by another batch. The property is now: "5"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=6
1>        Output Property: HighestNumber=6
1>        The property "HighestNumber" with value "5" is being overridden by another batch. The property is now: "6"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=7
1>        Output Property: HighestNumber=7
1>        The property "HighestNumber" with value "6" is being overridden by another batch. The property is now: "7"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=8
1>        Output Property: HighestNumber=8
1>        The property "HighestNumber" with value "7" is being overridden by another batch. The property is now: "8"
1>      Done executing task "CreateProperty".
1>      Task "CreateProperty"
1>        Task Parameter:Value=9
1>        Output Property: HighestNumber=9
1>        The property "HighestNumber" with value "8" is being overridden by another batch. The property is now: "9"
1>      Done executing task "CreateProperty".
1>      Task "Message"
1>        Task Parameter:Importance=High
1>        Task Parameter:Text=HighestNumber: 9
1>        HighestNumber: 9
1>      Done executing task "Message".
1>    Done building target "FindLargerNumber" in project "BaseLibrary.csproj".
1>  Done executing task "CallTarget".
1>  Task "Message"
1>    Task Parameter:Importance=High
1>    Task Parameter:Text=HighestNumber: 0
1>    HighestNumber: 0
1>  Done executing task "Message".

HighestNumber没有获得累积的最高数字,它会被每个批次目标踩到,然后在调用所有批次目标后返回0。

如何才能获得最高数量的物业?

1 个答案:

答案 0 :(得分:1)

当我们尝试使用批处理与条件或属性函数一起填充具有最高编号的属性时,MSBuild的行为不像我预期的那样(有关详细信息,请参阅我在问题下的评论)。鉴于此,我们可以回退创建内联任务并在c#中使用Enumerable.Max<Int32>。请注意,此实现会将无法解析为Int32的任何字符串(例如文件名)视为0

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="GetMax" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <Numbers ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />  
      <Max ParameterType="System.Int32" Output="true" />  
    </ParameterGroup>  
    <Task>  
      <Using Namespace="System.Linq"/>  
      <Code Type="Fragment" Language="cs">  
  <![CDATA[  
        if (Numbers.Length > 0)  
        {
          int number;
          Max = Numbers.Max(item => Int32.TryParse(item.ItemSpec, out number) ? number : 0);
        }  
  ]]>
      </Code>  
    </Task>  
  </UsingTask>

  <ItemGroup>
    <Number Include="*.txt" />
  </ItemGroup>

  <Target Name="PopulateMaxViaInlineTask">
    <GetMax Numbers="@(Number->'%(Filename)')">  
      <Output PropertyName="Max" TaskParameter="Max" />  
    </GetMax>  
    <Message Importance="High" Text="HighestNumber: $(Max)"/>
  </Target>
</Project>