Incrementing the feature version through MSBuild (Phil Hoff)

If you are using TeamBuild or MSBuild to build SharePoint projects, you can automatically increment the build number for the SharePoint feature version.

The following MSBuild code example can be added to a SharePoint project file (.csproj or .vbproj) to auto-increment the build number of all features in the package immediately prior to packaging.  It inserts a custom target between the generation of the project service graph and the actual manifest generation.  The target then invokes a custom, inline MSBuild task that takes each of the resolved features’ designer files, opens it, updates its Version property, then writes it back to disk. 

 <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\SharePointTools\
        Microsoft.VisualStudio.SharePoint.targets" />
<UsingTask TaskName="IncrementFeatureVersion" 
           TaskFactory="CodeTaskFactory" 
           AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">

<ParameterGroup>
<Features ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="Microsoft.VisualStudio.SharePoint" />
<Reference Include="Microsoft.VisualStudio.SharePoint.Designers.Models.Features" />
<Using Namespace="System.IO" />
<Using Namespace="Microsoft.VisualStudio.SharePoint.Features" />
<Using Namespace="Microsoft.VisualStudio.SharePoint.Designers.Models.Features" />
<Code Type="Fragment" Language="cs">
<![CDATA[
foreach (ITaskItem featureTaskItem in Features)
{
string fullPath = featureTaskItem.GetMetadata("FullPath");

// Ensure the file is read-write (as it may be read-only if not checked out of SCC).
File.SetAttributes(fullPath, File.GetAttributes(fullPath) & ~FileAttributes.ReadOnly);

Log.LogMessage(MessageImportance.High, String.Format("Feature: {0}", fullPath));

// Read the feature from the designer (*.feature) file.
IFeature feature = FeatureManager.ReadFeature(fullPath);

// If no version has been specified, assume 1.0 (no build or revision).
Version oldVersion = feature.Version ?? new Version(1, 0);

Log.LogMessage(MessageImportance.High, String.Format("Old Version: {0}", oldVersion));

// Increment the build number or start at 1, if old version did not specify one.
int newBuild = oldVersion.Build != -1 ? oldVersion.Build + 1 : 1;

Version newVersion = null;

if (oldVersion.Revision != -1)
{
// Create a new version using the existing revision.

     newVersion = new Version(oldVersion.Major, 
                              oldVersion.Minor, 
                              newBuild, 
                              oldVersion.Revision);

}
else
{
// Create a new version without a revision (as passing -1 for undefined will throw).
newVersion = new Version(oldVersion.Major, oldVersion.Minor, newBuild);
}

feature.Version = newVersion;

Log.LogMessage(MessageImportance.High, String.Format("New Version: {0}", feature.Version));

// Write the feature back to the designer (*.feature) file.
FeatureManager.WriteFeature(feature, fullPath);
}
]]>
</Code>
</Task>
</UsingTask>

<PropertyGroup>
<!-- Increment feature versions before packaging (i.e. before PerformEnumeration). -->
<CreatePackageDependsOn>
PerformIncrementFeatureVersion;
$(CreatePackageDependsOn);
</CreatePackageDependsOn>
</PropertyGroup>

<!--
Increments the Version attribute of each packaged feature's manifest.

Inputs: @(Feature)
Outputs: None

NOTE: The Feature ItemGroup is built by CreateSharePointProjectService, hence the target dependency.
-->
<Target Name="PerformIncrementFeatureVersion" DependsOnTargets="CreateSharePointProjectService">
<Message Importance="High" Text="Incrementing feature versions..." />
<IncrementFeatureVersion Features="@(Feature)" />
</Target>