我认为现在发生的事情并不是很清楚。在回答你的问题之前,让我们通过修改你的 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](https://istack.dev59.com/h2Tde.webp)
从这里我们可以看到目标本身被执行了两次。这是因为在目标上使用了
Outputs=%(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](https://istack.dev59.com/IIuEN.webp)
基于此,我们可以看到Build目标被执行了一次,并且出现错误,所以它没有像之前的例子那样第二次被执行。之后HandleErrors目标开始运行。在其中遇到了该元素。
<Message Text="Inside of the HandleErrors target" />
并且该消息已发送给记录器(请注意,这只会被调用一次)。之后便完成了。
<Message Text="Do some cleanup about %(Example.Color)" Importance="high" />
现在会出现两个消息语句。这是因为任务批处理已经开始运行了。该任务每个不同的 %(Example.Color) 批次被调用一次,其中的颜色值为 Red 和 Blue。因此,我们知道目标只被调用了一次(原始错误发生的地方),但你将整个 Example 项目集传递给它。
如果你想知道哪个值导致了错误,你需要在 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 内部,我只是设置了 _LastUsedColor 属性的值,然后如果出现错误,我就在该目标内使用相同的属性。当我构建此文件时,结果如下。
![enter image description here](https://istack.dev59.com/SMvVZ.webp)
我认为这就是你想要实现的。如果你不知道批处理是如何工作的,那么它会非常令人困惑。我在
http://sedotech.com/resources#Batching.上有许多关于批处理的在线资源。