How To: Retrieve the AssemblyVersion using AssemblyInfoTask
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 ]
Comments
Anonymous
March 19, 2008
Hi, I want to perform the same action as you describe in your post. Inded I have a solution composed of many class library, and for each dll I want to create a folder in my team project with the assembly name and his version. So, I try to use your code in my TfsBuild.proj (in TFS 2008) but after launching the build in Team build nothing happened. (AssemblyInfoTask is installed in the GAC). I try to debug it in the AfterBuild target in put a Message Text="..." but nothing appear in the log. Any idea ? Thanks. Regards Jean-michel I try to trace the commandAnonymous
July 06, 2010
Two problems with your blog entry. 1.) This example seems so increadibly incomplete as to be less than helpful. 2.) What don't use the community build extensions? Does Visual Studio make avaiable the generated version number? Or can you force the build just to read the one that was generated by visual studio for the current assembly?Anonymous
August 15, 2010
where is AssemblyInfoTask ?? thanks