How do I stop Item Batching from executing a batch when there are zero items?
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>