如何在MSBuild中批处理?

如何在MSBuild中批处理?,msbuild,Msbuild,我不知道如何像方法一样将值传递到MSBuild任务。获取以下项目文件 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Main"> <PropertyGroup> <Var1>Foo</Var1> <Var2>Bar</Var2> </Prope

我不知道如何像方法一样将值传递到MSBuild任务。获取以下项目文件

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Main">
<PropertyGroup>
    <Var1>Foo</Var1>
    <Var2>Bar</Var2>
</PropertyGroup>

<Target Name="Main">
    <Message Text="$(Var1)" Importance="high" />
    <Message Text="$(Var2)" Importance="high" />
</Target>   
</Project>

福
酒吧

我想将消息任务重构为一个目标,然后将Var1和Var2传递给它以获得相同的输出。这是一个非常简单的示例,但概念是相同的。

我想您应该这样做:

<ItemGroup>
  <Messages Include="Message1">
    <Text>Hello from Message1</Text>
  </Messages>
  <Messages Include="Message2">
    <Text>Hello from Message2</Text>
  </Messages>
</ItemGroup>

<Target Name="TestMessage">
  <Message Text="%(Messages.Text)"/>
</Target>

这是为了补充,而不是取代

有两种类型的配料。一种是当您使用
%(ItemName.MetaData)
语法时发生的情况。您只需将此值指定到任务参数中,就好像
%(ItemName.MetaData)
只会扩展到一个特定值一样。然后,MSBuild会自动执行该任务多次,从而避免了该任务需要显式支持对项列表的迭代

另一种批处理类型是。使用
输入和
输出属性时,会发生目标批处理。要批量处理任意一组项目,使目标在每个项目上只执行一次,可以指定
Inputs=“@(ItemName)”Outputs=%(Identity).bogus
。重要的是,
%(标识)
存在。批处理将查看
输入
输出
的所有可能扩展,并根据这些扩展决定其批处理。因此,如果希望目标分别为每个项目运行,则必须确保每个项目都有一个唯一的扩展。我给出了@BryanJ的代码,并对其进行了修改,以使用这种风格的目标批处理:

<?xml version="1.0"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="all">
  <ItemGroup>
    <Messages Include="Message1">
      <Text>Hello from Message1</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message2">
      <Text>Hello from Message2</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message3">
      <Text>Hello from Message3</Text>
      <Group>2</Group>
    </Messages>
  </ItemGroup>
  <Target Name="all" DependsOnTargets="TestMessage;TestMessageGrouping" />
  <!--
      Use the Inputs/Outputs attributes to specify Target
      batching. The metadata value I am batching over is
      Identity. Since Identity is unique per item, this means the
      Target will get run in full once for every value in
      Messages. We provide something bogus for Outputs. It is
      important that our bogus values do not coincide with real
      filenames. If MSBuild finds a file with the name of a value
      in Outputs and another file, with an older timestamp,
      matching the corresponding value in Inputs, it will skip
      running this Target. (This is useful in many situations, but
      not when we want to just print out messages!)
  -->
  <Target Name="TestMessage" Inputs="@(Messages)" Outputs="%(Identity).bogus">
    <Message Text="I will print the Text metadata property of %(Messages.Identity)" />
    <Message Text="%(Messages.Text)" />
  </Target>
  <!--
      If you want to combine Task and Target batching, you can specify
      a different metadata value than Identity to group the items
      by. I use the Group metadata I specified in the ItemGroup.
  -->
  <Target Name="TestMessageGrouping" Inputs="@(Messages)" Outputs="%(Group).bogus">
    <Message Text="I will print the Text metadata property of all messages from Group %(Messages.Group)" />
    <!--
        Now, within the Target batch, we use Task batching to print
        all of the messages in our %(Messages.Group) at once.
    -->
    <Message Text="%(Messages.Text)" />
  </Target>
</Project>

比如?@KMoraz不,那篇文章指的是延迟名称解析。我想做的是将多个变量传递给目标,然后让目标像处理方法一样处理每个变量。是的!这正是我所追求的,但在这样做的过程中,我发现了一个相关的问题。如果在Message任务之后有另一个任务,则在继续执行下一个任务之前,将对Messages ItemGroup中的所有项目执行Message任务。如何让任务A、任务B和任务C按顺序运行ItemGroup中的每个项目?我不知道这是否可行。最简单的方法是创建目标A、目标B和目标C,让每个目标执行消息任务,然后执行您希望它运行的任务。否则,您可以编写自己的自定义MSBuild任务,该任务接收消息和目标/任务名称,然后像这样调用它。在我看来,第一种选择似乎容易得多。目标批处理(相对于基于任务的批处理)是可能的。将Outputs=“%”(Messages.Identity)”添加到Target元素应该可以做到这一点,它将指示整个目标应该被批处理,每个项目的执行与值无关。Sayed有一个很好的描述,这里有详细的例子:
<?xml version="1.0"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="all">
  <ItemGroup>
    <Messages Include="Message1">
      <Text>Hello from Message1</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message2">
      <Text>Hello from Message2</Text>
      <Group>1</Group>
    </Messages>
    <Messages Include="Message3">
      <Text>Hello from Message3</Text>
      <Group>2</Group>
    </Messages>
  </ItemGroup>
  <Target Name="all" DependsOnTargets="TestMessage;TestMessageGrouping" />
  <!--
      Use the Inputs/Outputs attributes to specify Target
      batching. The metadata value I am batching over is
      Identity. Since Identity is unique per item, this means the
      Target will get run in full once for every value in
      Messages. We provide something bogus for Outputs. It is
      important that our bogus values do not coincide with real
      filenames. If MSBuild finds a file with the name of a value
      in Outputs and another file, with an older timestamp,
      matching the corresponding value in Inputs, it will skip
      running this Target. (This is useful in many situations, but
      not when we want to just print out messages!)
  -->
  <Target Name="TestMessage" Inputs="@(Messages)" Outputs="%(Identity).bogus">
    <Message Text="I will print the Text metadata property of %(Messages.Identity)" />
    <Message Text="%(Messages.Text)" />
  </Target>
  <!--
      If you want to combine Task and Target batching, you can specify
      a different metadata value than Identity to group the items
      by. I use the Group metadata I specified in the ItemGroup.
  -->
  <Target Name="TestMessageGrouping" Inputs="@(Messages)" Outputs="%(Group).bogus">
    <Message Text="I will print the Text metadata property of all messages from Group %(Messages.Group)" />
    <!--
        Now, within the Target batch, we use Task batching to print
        all of the messages in our %(Messages.Group) at once.
    -->
    <Message Text="%(Messages.Text)" />
  </Target>
</Project>
TestMessage:
  I will print the Text metadata property of Message1
  Hello from Message1
TestMessage:
  I will print the Text metadata property of Message2
  Hello from Message2
TestMessage:
  I will print the Text metadata property of Message3
  Hello from Message3
TestMessageGrouping:
  I will print the Text metadata property of all messages from Group 1
  Hello from Message1
  Hello from Message2
TestMessageGrouping:
  I will print the Text metadata property of all messages from Group 2
  Hello from Message3