We got a great question at msbuild@microsoft.com last week:

What is the preferred method to retrieve the version of the assembly that was just built via MSBuild? Post build, we would like to automatically create and copy the assembly(ies) to version folder.

If you are using the AssemblyInfoTask and its associated Microsoft.VersionNumber.Targets file this is really easy. Here's what you do:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\AssemblyInfoTask\Microsoft.VersionNumber.Targets"/>

 

<Target Name="AfterBuild" Condition="$(MaxAssemblyVersion) != ''">
   <MakeDir Directories="c:\archive\$(AssemblyName)\$(MaxAssemblyVersion)"/>
   <
CreateItem Include="$(OutputPath)\**\*.*">
      <
Output TaskParameter="Include" ItemName="FilesToArchive"/>
   </
CreateItem>
   <
Copy SourceFiles="@(FilesToArchive)" DestinationFolder="c:\archive\$(AssemblyName)\$(MaxAssemblyVersion)\%(FilesToArchive.RecursiveDir)"/>
</
Target>

 

Now that I look at this, perhaps "really easy" isn't the right way to describe it :) In fact, I had to have Faisal show me how to do the recursive copy, and Kieran help me figure out that a CreateItem was needed.

 

The $(MaxAssemblyVersion) property holds the version number for the build. This is used with the MakeDir task to create the directory. The CreateItem task is used to collect all the files from the output directory into an item group so it can then be copied recursively using the Copy task. Note the use of the RecursiveDir metadata, as described in Faisal's post on recursive copy to ensure all the files are copied as a full directory tree into the archive directory.

 

The condition on AfterBuild prevents the directory from being created if the MaxAssemblyVersion wasn't set during the build. This happens when none of the files changed, and nothing was re-built. Instead of depending on the $(MaxAssemblyVersion) property you could also set up the Inputs and Outputs to the target to be very specific about what file updates will trigger a copy to the archive directory.

If you're interesed in where $(MaxAssemblyVersion) comes from, it is set by the Microsoft.VersionNumber.Targets file when the AssemblyInfoTask is run. The snippet from the .targets file looks like this:

<AssemblyInfo [... junk removed for clarity ... ]>
    <
Output TaskParameter="MaxAssemblyVersion" PropertyName="MaxAssemblyVersion"/>
    <Output TaskParameter="MaxAssemblyFileVersion" PropertyName="MaxAssemblyFileVersion"/>
</AssemblyInfo>

This causes the value of the "MaxAssemblyVersion" property on the AssemblyInfo class (the one in .NET code) to get stuck in the MSBuild "MaxAssemblyVersion" property after the task is run. The same thing happens for MaxAssemblyFileVersion.

[ Author: Neil Enns ]