我正在使用目标的批处理,我希望能够执行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目标运行两次,每种颜色一次。有没有办法让它只运行失败期间激活的颜色?
答案 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>
当我从命令行构建它时,结果是。 从这里我们可以看到目标本身被执行了两次。这是因为在目标上,您使用输出=%(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>
当我构建它时,结果是。 基于此,我们可以看到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属性的值,然后如果发生错误,我只是在该目标内使用相同的属性。当我构建这个文件时,结果是。
我认为这是你想要完成的事情。如果您不知道它是如何工作的,那么批处理会非常混乱。我在网上获得了大量关于http://sedotech.com/resources#Batching.
批处理的资源答案 1 :(得分:0)
IIUC,您的HandleErrors将分别进行批量处理。
您将有条件地或无条件地使用错误任务。在任何一种情况下,您都应该能够使用MSBuild任务来调用HandleErrors并将%(Example.Color)作为属性传递。类似的东西:
<MSBuild Targets="HandleErrors" Properties="ErrorColor=%(Example.Color)" />
另一种方法是,在出现错误时创建一个属性,并在HandleErrors目标中使用它。虽然上述方法会更清晰。