How do I stop Item Batching from executing a batch when there are zero items?
Execute this with msbuild:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Main" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Colors Include="Blue">
<Shade>Dark</Shade>
</Colors>
</ItemGroup>
<Target Name="Main">
<Message Text="Color: %(Colors.Shade) %(Colors.Identity)"/>
</Target>
</Project>
And it outputs:
Color: Dark Blue
All well, and good, but delete the color and use this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Main" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
</ItemGroup>
<Target Name="Main">
<Message Text="Color: %(Colors.Shade) %(Colors.Identity)"/>
</Target>
</Project>
And it outputs:
Color:
Why is one batch of the Message task being executed when there are no items in the group? I would have expected for zero items, the batch would execute zero times and I would not see "Color:" followed by nothing in the output.
Am I doing something wrong or is there a workaround for this?
Thanks.
Update: I've found you can do:
<Message Condition="'@(Colors)'!=''" Text="Color: %(Colors.Shade) %(Colors.Id开发者_运维技巧entity)"/>
But, if feels unsatisfactory to have to explicitly write code for the case when there are no items every time batching is used.
My 2 cents :
In your Message Task, there is information from Batching and static information ("Colors :"). I think MsBuild prints the static information and then batch over the values of your Colors Item. The probleme is that you don't have any data in your collection (it is even undeclared), I suppose MsBuild interpretates this as an empty list, which, when you try to print it, print the empty string ''.
If you remove the static content ("Colors :" and the whitespace before identity), you won't have anything displayed.
A solution for printing with batching only if the items collection is not empty would be either :
Check if the collection is empty
<Message Condition="'@(Colors)'!=''" Text="Color: %(Colors.Shade) %(Colors.Identity)"/>
Use MSBuild transforms
<Message Text="@(Colors->'Color : %(Shade) %(Identity)')"/>
Just wanted to add an alternative solution for this as well. If you can change your batching to Target batching, instead of Task batching, you can add your Condition statement to the Target.
I added the Target batching here:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Main" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
</ItemGroup>
<Target Name="Main" Outputs="%(Colors.Identity)">
<Message Text="Color: %(Colors.Shade) %(Colors.Identity)"/>
</Target>
</Project>
...and that can be conditionally made to only execute when something exists in the Colors item group:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Main" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
</ItemGroup>
<Target Condition="'@(Colors)'!=''" Name="Main" Outputs="%(Colors.Identity)">
<Message Text="Color: %(Colors.Shade) %(Colors.Identity)"/>
</Target>
</Project>
精彩评论