Getting the Combination of Two ItemGroups in MSBuild

In a project recently we needed a way to generate the combinations of two ItemGroups to build a release package with folders for environments and several copies of a program within each environment folder.

As MSBuild does not have an easy way to iterate through two collections to build such a combinations we need to take some advantage of how MSBuild handles collections.

We can take advantage of this by creating a new ItemGroup using one of the ItemGroups we want to combine and creating a new property on this new ItemGroup using the collection defined by the second ItemGroup we want to combine

The below snippet shows this in action. Try it out by copying into a text file, saving it, and running it with MSBuild.exe.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="DressPerson"
 xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<ItemGroup>
<Person Include="Item">
<Name>Alice</Name>
</Person>
<Person Include="Item">
<Name>Bob</Name>
</Person>
<ItemOfClothing Include="Item">
<Name>Shirt</Name>
</ItemOfClothing>
<ItemOfClothing Include="Item">
<Name>Shorts</Name>
</ItemOfClothing>
</ItemGroup>

<Target Name="DressPerson">
<!-- Neat way to get the combinations of two ItemGroups http://stackoverflow.com/a/18032552/41492 -->
<ItemGroup>
<Combined Include="@(Person)">
<ItemOfClothingName>%(ItemOfClothing.Name)</ItemOfClothingName>
</Combined>
</ItemGroup>

<Message Text="%(Combined.Name) -- %(Combined.ItemOfClothingName)" />
</Target>
</Project>

Huge thanks to the user Dog Ears on StackOverflow whose answer put me on the right path. http://stackoverflow.com/a/18032552/41492