If you add this to your project file:
<ItemGroup>
<CADYears Include="2013;2014;2015"/>
</ItemGroup>
<Target Name="BatchRebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>
and call
msbuild <path_to_projectfile> /t:BatchRebuild
on the commandline, it will build path_to_projectfile 3 times each with a different CAD_Year property.
To get this invoked by VS is trickier since you need to override the Rebuild target, but this for instance works for VS2013 (Actualrebuild
target was copied from the Rebuild
target in C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Common.CurrentVersion.targets):
<ItemGroup>
<CADYears Include="2013;2014;2015"/>
</ItemGroup>
<Target Name="ActualRebuild"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(RebuildDependsOn)"
Returns="$(TargetPath)"/>
<Target Name="BatchRebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="ActualRebuild" Properties="CAD_Year=%(CADYears.Identity)"/>
</Target>
<Target Name="Rebuild">
<Msbuild Projects="$(MsBuildThisFile)" Targets="BatchRebuild"/>
</Target>
Edit
Since the template system in VS tries to copies ItemGroups it finds in the project root (which seems like a bug to me, or at the least a very annoying feature) you can work around that by using a property and converting it into an item when needed:
<PropertyGroup>
<CADYears>2013;2014;2015<CADYears/>
</PropertyGroup>
<Target Name="BatchRebuild">
<ItemGroup>
<CADYearsItem Include="$(CADYears)"/>
</ItemGroup>
<Msbuild Projects="$(MsBuildThisFile)" Targets="Rebuild" Properties="CAD_Year=%(CADYearsItem .Identity)"/>
</Target>
Note: in the project you posted in the link you are invoking the Rebuild target in the Afterbuild target. I didn't try it, but that will almost certainly lead to infinite recursion. So you should stick to a solution like posted above with a seperate target.