Using the FeatureUpgrading event to upgrade features
In SharePoint 2010 there is now a way to control how features are upgraded from one version to another. Here’s how to get it working, using the new FeatureUpgrading event in the feature receiver class.
Writing the upgrade code
Add an event receiver to your feature, and uncomment the FeatureUpgrading method. This method will run whenever your feature is being upgraded.
Next, go to the feature properties, and copy the values for Receiver Assembly and Receiver Class to Upgrade Actions Receiver Assembly and Upgrade Actions Receiver Class, and set an initial value for the Version property, for instance 1.0.0.0.

The Version is on the same format as .Net assembly versions, ie. Major.Minor.Build.Revision.
Deploy the solution, then go back and increase the Version, for instance to 1.0.0.1. Open the feature designer, and click on Manifest.
Click on Edit options. This allows you to add XML to your feature that will be merged with what you’ve configured in the feature designer and the feature properties. Enter the following:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<Feature xmlns=”http://schemas.microsoft.com/sharepoint/“>
<UpgradeActions>
<VersionRange>
<CustomUpgradeAction Name=”DoTheUpgrade”/>
</VersionRange>
</UpgradeActions>
</Feature>
You can specify multiple VersionRange elements that apply different upgrade actions to different version ranges, by using the BeginVersion and EndVersion attributes. If you don’t specify these values, like above, the same upgrade actions are taken no matter which version we’re upgrading from, so then it’s up to your code to determine what it needs to do. You can access the latest and current version numbers from properties.Definition.Version (latest) and properties.Feature.Version (current).
The CustomUpgradeAction element is the node that actually triggers the call to FeatureUpgrading. The Name property is sent to the method as the parameter upgradeActionName, and you can use that to determine which upgrade action to perform, like this:
<VersionRange BeginVersion=”1.0.0.0″ EndVersion=”2.0.0.0″>
<CustomUpgradeAction Name=”UpgradeToV2″/>
</VersionRange>
<VersionRange BeginVersion=”2.0.0.0″ EndVersion=”3.0.0.0″>
<CustomUpgradeAction Name=”UpgradeToV3″/>
</VersionRange>
And in the feature receiver class:
public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
{
switch (upgradeActionName)
{
case “UpgradeToV2″:
..
case “UpgradeToV3″:
..
}
}
We can now deploy the new version. Do not use Visual Studio to do this, since the default deployment action in Visual Studio is to retract the solution and then add it back in again. Instead, just package the solution, then use the update-spsolution command in PowerShell:
update-spsolution -identity SharePointProject3.wsp -literalpath bin\Debug\SharePointProject3.wsp -GACDeployment
(Note: You should probably start a new instance of PowerShell after each time you build, otherwise the actions you perform may be run against an outdated version of your assembly from the GAC. The same thing sometimes applies to Visual Studio deployment, for instance if one solution refers to an assembly in another solution – hopefully this is a bug in the beta.)
Performing the upgrade
At this point the new version of the feature has been installed, but it has not been upgraded on the sites where it is in use. You can verify this by running the following script in PowerShell:
get-spfeature | where {$_.DisplayName -eq “FeatureName”} | select DisplayName, Version
This is the latest version. Here’s the version currently in use on your site:
(get-spsite http://[siteurl]).Features | where {$_.Definition.DisplayName -eq “FeatureName”} | select Version
If you’ve done everything correctly, the versions should differ. It’s now time to perform the actual upgrade. Features aren’t upgraded automatically. There are two ways to trigger an upgrade, one slow and one quick.
The slow way is to run psconfig:
psconfig -cmd upgrade -inplace b2b
This will take several minutes, but is probably the correct way to perform an upgrade in a test or production environment. “-inplace b2b” means that features will be upgraded if any part of the version has been increased, even the build or revision number. If you specify “-inplace v2v”, features will only be upgraded if the major or minor version number has increased, ie. 1.1.0.0 => 1.2.0.0.
A quicker way to perform an upgrade is to call the Upgrade method on the SPFeature object directly on the site where it is activated.
$site = get-spsite http://siteurl
$enabledfeature = $site.Features | where {$_.Definition.DisplayName -eq “FeatureName” }
if($enabledfeature)
{
$enabledfeature.Upgrade($false)
}
This may be a useful script to run on your development server when you want to test that your upgrade code is running correctly.
Now if you check the current version again, it should be the latest version. Note that you’re upgrading the feature only on one particular site. Also note that the feature in this example is Site-scoped. For other scopes, run the upgrade at the appropriate level.
In addition to executing upgrade code, you can also specify other actions in the VersionRange element, such as adding a field to a content type, or renaming a module file.
Sources and more information
Corey Roth: Feature Versioning and Upgrades in SharePoint 2010
Dave Graham: In-place Upgrade of Solutions in SharePoint 2010
MSDN: How to: Use Upgrade Code to Activate a Feature with Dependencies

[...] solution is to use a feature upgrade, as described in an earlier post, and then in the FeatureUpgrading method do the [...]
Getting multiple layers of web.config modifications to live together « The SI SharePoint Blog
January 22, 2010 at 11:00 am
[...] instance, you could have one configuration that retracts and installs the solution, another that upgrades an existing solution, and one that just adds your assemblies directly to the GAC, (in order to save time when all [...]
Make your own PowerShell scripts for SharePoint deployment in Visual Studio 2010 « The SI SharePoint Blog
March 25, 2010 at 4:11 pm
[...] different build configurations to choose between different deployment scenarios: Full reinstall, upgrade from previous version, [...]
Getting around GAC problems when you deploy SharePoint solutions with PowerShell « The SI SharePoint Blog
March 26, 2010 at 2:58 pm