Going beyond files with ItemGroup

If you Google for information on the ItemGroup element of MSBuild, most of the top search results will discuss its use in dealing with files.  The ItemGroup element is far more flexible than this, as I figured out today when making changes to an MSBuild script for creating databases.

My goal was to simplify the targets I was using to create local groups and add users to them.  I started with an example on pages 51-52 of Inside the Microsoft Build Engine: Using MSBuild and Team Foundation Build, where the author uses an ItemGroup to create a list of 4 servers.  Each server has custom metadata associated with it.  In his PrintInfo target, he displays the data, overrides an element with new data, and even removes an element.  Because MSBuild supports batching, you can declare a task and attributes once and still execute it multiple times.  Here’s how I leveraged this capability:

  1. I created a target that stored the username of the logged-in user in a property.
  2. I created an ItemGroup.  The metadata for each group element was the name of the local group I wanted to create.
  3. I wrote the Exec commands to execute on each member of the ItemGroup

The ItemGroup looks something like this:

<LocalGroup Include=”Group1″>
<LocalGroup Include=”Group2″>
<LocalGroup Include=”Group3″>

The Exec commands for deleting a local group if it exists, creating a local group, and adding the logged-in user to it, look like this:

<Exec Command=”net localgroup %(LocalGroup.Name) /delete” IgnoreExitCode=”true” />
<Exec Command=”net localgroup %(LocalGroup.Name) /add” IgnoreExitCode=”true” />
<Exec Command=”net localgroup %(LocalGroup.Name) $(LoggedInUser) /add” />

The result is that these commands are executed for each member of the ItemGroup.  This implementation makes a lot easier to add more local groups if necessary, or make other changes to the target.