Theme-amajig Refactored: Using Feature Properties

In a previous post, I described a feature that would take install and retract modifications to SPTHEMES.XML. Peter Seale suggested providing a method to reapply the changes without a deactivate/activate cycle, specifically for new servers added to a farm. It should be as simple as providing a user interface to call FeatureThemesJob.InstallThemes, but that presents a bit of a problem: InstallThemes expects the name of the themes file, which I declare in the feature receiver. So before we can work on a reapplication interface, let’s move that file name to a more accessible location.

The Revised Feature

A better way to store the theme file name would be as a Feature Property:

  Title="SPHOLS Themes"
  Description="Installs SPHOLS and SPHOLSX themes on farm."
  ReceiverAssembly="MyBranding, ..."
    <ElementFile Location="SPTHEMES.XML" />
    <Property Key="Solutionizing:ThemesFile" Value="SPTHEMES.XML" />

And we can remove references to THEMES_FILE from our receiver:

namespace MyBranding {
  public class MyThemesFeatureReceiver : SPFeatureReceiver {
    public override void FeatureActivated(SPFeatureReceiverProperties properties) {
      if (properties == null)
        throw new ArgumentNullException("properties");

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties) {
      if (properties == null)
        throw new ArgumentNullException("properties");

    public override void FeatureInstalled(SPFeatureReceiverProperties properties) { }
    public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }

Note that this code is now completely feature-agnostic, reusable for any themes feature.


Other than purging the logic to persist _themesFile, which I’ll leave as an exercise for the reader, we just need to update Execute to use our new feature property:

    private const string PROP_THEMES_FILE = "Solutionizing:ThemesFile"
    private const string SPTHEMES_PATH = @"TEMPLATE\LAYOUTS\1033\SPTHEMES.XML";
    public override void Execute(Guid targetInstanceId) {
      SPFeatureDefinition fDef = Farm.FeatureDefinitions[_featureID];
      if (fDef != null) {
        SPFeatureProperty themesFileProp = fDef.Properties[PROP_THEMES_FILE];
        if(themesFileProp == null)
          throw new SPException(string.Format("Feature '{0}' is missing property '{1}'.", fDef.DisplayName, PROP_THEMES_FILE));

        DoMerge(SPUtility.GetGenericSetupPath(SPTHEMES_PATH), Path.Combine(fDef.RootDirectory, themesFileProp.Value));

But since we’re in a refactoring mood, we might as well extract the code to retrieve the themes file path:

    internal const string PROP_THEMES_FILE = "Solutionizing:ThemesFile"
    private const string ERR_FEATURE_NOT_FOUND = "Feature '{0}' not found in farm.";
    private const string ERR_MISSING_PROPERTY = "Feature '{0}' is missing property '{1}'.";
    internal string ThemesFilePath {
      get {
        SPFeatureDefinition fDef = Farm.FeatureDefinitions[_featureID];
        if (fDef == null)
          throw new SPException(string.Format(ERR_FEATURE_NOT_FOUND, _featureID));

        SPFeatureProperty prop = fDef.Properties[PROP_THEMES_FILE];
        if (prop == null)
          throw new SPException(string.Format(ERR_MISSING_PROPERTY, fDef.DisplayName, PROP_THEMES_FILE));

        return Path.Combine(fDef.RootDirectory, prop.Value);

Which makes Execute rather elegant:

    private const string SPTHEMES_PATH = @"TEMPLATE\LAYOUTS\1033\SPTHEMES.XML";
    public override void Execute(Guid targetInstanceId) {
      DoMerge(SPUtility.GetGenericSetupPath(SPTHEMES_PATH), ThemesFilePath);

Now everything we need for the timer job is available from the feature definition. The next step is to build an interface to run the job on demand. Stay tuned!


3 Responses to “Theme-amajig Refactored: Using Feature Properties”

  1. Theme-amajig: Updating SPTHEMES.XML Through a Feature « Solutionizing .NET Says:

    […] 7/13/2008: Theme-amajig Refactored: Using Feature Properties Possibly related posts: (automatically generated)HttpModule to set the default themeDeliver a […]

  2. Links (7/15/2008) « Steve Pietrek - Everything SharePoint Says:

    […] Theme-amajig Refactored: Using Feature Properties […]

  3. STSDEV Theme Solution Generator « Solutionizing .NET Says:

    […] we developers all know the answer is yes. I’ve previously discussed updating SPTHEMES.XML, and there are several tools (WSPBuilder, STSDEV, VSeWSS (in theory)…) […]

Comments are closed.

%d bloggers like this: