How to handle errors when using target package in msbuild?

I use batch processing for the purpose, and I want to be able to do an OnError-specific cleanup for iterating where the error occurred. Here's a fully generalized example:

<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> 

Assembly fails when the color is blue. But HandleErrors Target runs twice, once for each color. Is there a way to make it work only for the color that was active during the crash?

+4
source share
2 answers

I think it is unclear what exactly is here. Before we get to your question, let's see what happens by modifying your proj file.

Below is the modified sample-no-error.proj file, in which I deleted the error parts and simply added the Message task there.

 <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> 

When I create this from the command line, the result is obtained. enter image description here From this we see that the goal itself was fulfilled twice. This is due to the fact that on the target you decorated it with Outputs =% (Example.Color) .txt . When you use % (...) , you start the release of MSBuild. There are two types of dosing; target dosing, batch task. Target grouping is where the whole goal is fulfilled per party (this is what you are doing here). Task assignment is the execution of a task for each batch.

I have one more sample, which is exactly what you have, except that I added an additional message statement inside the Build object.

 <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> 

When I build this, we get the result. enter image description here Based on this, we see that the build target was executed once, and an error occurred, so it was not executed a second time, as in the previous example, where there was no error. After that I clicked the HandleErrors icon. Inside this, he came across an element.

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

And the message was sent to the registrars (note that this was called only once). After that he came.

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

Now this has led to two reports. This is due to the fact that the intimidation of tasks began here. The task is called once for a unique batch of% (Example.Color), which is red and blue. Thus, we know that the target was called only once (when the original error occurred), but you pass it the whole set of Example elements.

If you want to know what value caused the error, you will need to track this in your Build target. You can simply put the current color in the property and then refer to it in your HandleErrors target. For example, consider the example-id-errors.proj below.

 <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> 

Here you can see that inside Build, I just set the value for the _LastUsedColor property, and then if an error occurs, I just use the same property inside this target. When I create this file, the results will be.

enter image description here

I think this is what you are trying to achieve. Packing is pretty confusing if you don't know how this works. I have a bunch of resources on the Internet regarding batch processing at http://sedotech.com/resources#Batching.

+9
source

IIUC, your HandleErrors will be separately packaged.

You would use the Error task both conditionally and unconditionally. In any case, you should use MSBuild to call HandleErrors and pass% (Example.Color) as a property. Sort of:

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

Another way could be to create a property in case of an error and use it in the target HandleErrors. Although the above approach will be cleaner.

0
source

Source: https://habr.com/ru/post/1388405/


All Articles