在MSBuild中,如何聚合ItemGroup(特别是在组的元数据中查找最大的数字?)

在MSBuild中,如何聚合ItemGroup(特别是在组的元数据中查找最大的数字?),msbuild,Msbuild,我已尝试通过包含以下编号的元数据字段使用批处理目标进行批处理: <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <HighestNumber>0</HighestNumber>

我已尝试通过包含以下编号的元数据字段使用批处理目标进行批处理:

<?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>
HighestNumber并没有得到累计的最大值,它被每个批处理目标踩死,然后在调用所有批处理目标后返回到0


如何在属性中获取最大值?

MSBuild的行为与我在尝试将批处理与条件或属性函数结合使用以最大值填充属性时预期的行为不同(有关详细信息,请参阅问题下的注释)。考虑到这一点,我们可以回过头来创建一个内联任务,并在c#中使用
Enumerable.Max
。请注意,此实现将无法解析为
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>


0)  
{
整数;
Max=Numbers.Max(item=>Int32.TryParse(item.ItemSpec,out number)?编号:0);
}  
]]>


您使用的是最新可用的MSBuild版本吗?我想知道这是否可以由解决。您还可以监视一个未解决的MSBuild问题,我刚刚发布了两个受您问题启发的简化复制:也许这将产生一个解释、解决方法和/或最终的修复。dotnet MSBuild/?有以下版本:Microsoft(R)针对.NET CoreOK的构建引擎版本15.4.8.50001,这是最新版本。我将等待一段时间,看看是否有来自微软的人对我的评论进行了回复。我昨天刚刚在InlineTask中发现了这一点,并希望做到这一点,但后来发现它在针对.Net Core时不起作用,因此,我创建了一个小程序集,其中包含一个任务,该任务中包含相同的代码。@JeremyMorton-我的回答与您的问题相符(您的问题没有提到您的目标是.Net Core)。请考虑接受我的回答,或是投票,提交和接受你自己的答案。
<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>