如何在msbuild中使用目标批处理时处理错误?

时间:2011-12-29 03:36:36

标签: msbuild

我正在使用目标的批处理,我希望能够执行OnError清理,该清理特定于发生错误的迭代。这是一个完全通用的例子:

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

<ItemGroup>
    <Example Include="Item1">
        <Color>Blue</Color>
    </Example>
    <Example Include="Item2">
        <Color>Red</Color>
    </Example>
</ItemGroup>

<Target Name="Build"
    Inputs="@(Example)"
    Outputs="%(Example.Color).txt">
    <Error Text="An error occurred during %(Example.Color)" />
    <OnError ExecuteTargets="HandleErrors" />
</Target>

<Target Name="HandleErrors">
    <Message Text="Do some cleanup about %(Example.Color)" Importance="high" />
</Target>

</Project>

当Color为Blue时,Build目标失败。但HandleErrors目标运行两次,每种颜色一次。有没有办法让它只运行失败期间激活的颜色?

2 个答案:

答案 0 :(得分:9)

我认为尚不清楚完全在这里发生了什么。在我们回答您的问题之前,让我们通过修改您的proj文件来了解正在发生的事情。

下面是一个修改过的文件sample-no-error.proj,我在其中删除了错误部分,并在那里添加了一个Message任务。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
  <ItemGroup>
      <Example Include="Item1">
          <Color>Blue</Color>
      </Example>
      <Example Include="Item2">
          <Color>Red</Color>
      </Example>
  </ItemGroup>

  <Target Name="Build"
      Inputs="@(Example)"
      Outputs="%(Example.Color).txt">

    <Message Text="Inside of Build, color: %(Example.Color)" />
  </Target>  
</Project>

当我从命令行构建它时,结果是。 enter image description here 从这里我们可以看到目标本身被执行了两次。这是因为在目标上,您使用输出=%(Example.Color).txt 进行装饰。当您使用%(...)时,您将启动MSBuild批处理。批处理有两种;目标批处理,任务批处理。目标批处理是每批执行整个目标的位置(这是您在此处进行的操作)。任务批处理是每批执行任务的地方。

除了我在Build目标中添加了一个额外的Message语句之外,我还有另一个样本,这正是你所拥有的。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
  <ItemGroup>
      <Example Include="Item1">
          <Color>Blue</Color>
      </Example>
      <Example Include="Item2">
          <Color>Red</Color>
      </Example>
  </ItemGroup>

  <Target Name="Build"
      Inputs="@(Example)"
      Outputs="%(Example.Color).txt">

    <Message Text="Inside of Build, color: %(Example.Color)" />

    <Error Text="An error occurred during %(Example.Color)" />
    <OnError ExecuteTargets="HandleErrors" />
  </Target>

  <Target Name="HandleErrors">
    <Message Text="Inside of the HandleErrors target" />
    <Message Text="Do some cleanup about %(Example.Color)" Importance="high" />
  </Target>
</Project>

当我构建它时,结果是。 enter image description here 基于此,我们可以看到Build目标执行了一次,并且发生了错误,因此它没有像上一个没有错误的例子那样第二次执行。之后,HandleErrors目标开始了。在其中遇到了元素。

<Message Text="Inside of the HandleErrors target" />

并且消息被发送到记录器(注意这只被调用一次)。之后就来了。

<Message Text="Do some cleanup about %(Example.Color)" Importance="high" />

现在这产生了两个消息语句。那是因为任务批处理已经开始在这里启动。每个唯一批次的%(Example.Color)(红色和蓝色)调用该任务一次。所以我们知道目标只被调用一次(原始错误发生的地方),但是你将整个示例项集传递给它。

如果您想知道产生错误的值,您必须在Build目标中跟踪它。您可以将当前颜色放在属性中,然后在HandleErrors目标中引用它。例如,看看下面的sample-id-errors.proj。

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
  <ItemGroup>
      <Example Include="Item1">
          <Color>Blue</Color>
      </Example>
      <Example Include="Item2">
          <Color>Red</Color>
      </Example>
  </ItemGroup>

  <Target Name="Build"
      Inputs="@(Example)"
      Outputs="%(Example.Color).txt">
    <PropertyGroup>
      <_LastUsedColor>%(Example.Color)</_LastUsedColor>
    </PropertyGroup>

    <Message Text="Inside of Build, color: %(Example.Color)" />

    <Error Text="An error occurred during %(Example.Color)" />
    <OnError ExecuteTargets="HandleErrors" />
  </Target>

  <Target Name="HandleErrors">
    <Message Text="Inside of the HandleErrors target" />
    <Message Text="The color which caused the error was: $(_LastUsedColor)"/>
  </Target>
</Project>

在这里你可以看到Build I内部只设置_LastUsedColor属性的值,然后如果发生错误,我只是在该目标内使用相同的属性。当我构建这个文件时,结果是。

enter image description here

我认为这是你想要完成的事情。如果您不知道它是如何工作的,那么批处理会非常混乱。我在网上获得了大量关于http://sedotech.com/resources#Batching.

批处理的资源

答案 1 :(得分:0)

IIUC,您的HandleErrors将分别进行批量处理。

您将有条件地或无条件地使用错误任务。在任何一种情况下,您都应该能够使用MSBuild任务来调用HandleErrors并将%(Example.Color)作为属性传递。类似的东西:

<MSBuild Targets="HandleErrors" Properties="ErrorColor=%(Example.Color)" />

另一种方法是,在出现错误时创建一个属性,并在HandleErrors目标中使用它。虽然上述方法会更清晰。