SharePoint Health Rules: My Sample Rule Catches Lazy Customization Deployments

A feature I was happy to see added to SharePoint 2010 was the health rules. Administrators can be tipped off when something is not quite right with a farm. Although there are a fantastic number of rules already defined and built in, I really like how easy and straight forward it is to create custom rules. The SPHealthAnalysisRule class has a Check method that is available to simply override and implement your own logic.
One thing I use to do when I looked after a number of farms was to run a number of scripts on the farm that assessed the health, evaluated usage, or the like. By reworking these scripts into health rules, they can run and report the health of the farm on a regular schedule. One example I’ve included below is a check that determines if any features have been deployed through a copy & paste of the feature files on the servers rather than through the preferred method of packaging them into a SharePoint solution package.
Other uses for custom health rules can include things like checking the lifecycle of a site and notifying with an informative list of sites that appear to have gone dormant. Or even for non-administrator health related checks, a custom health rule can check patterns of usage or inappropriate usage, monitor repositories, check if ex-employees are the sole owners of content, or maybe if content is persisting for long periods of time yet haven’t been declared a record. It is exciting all the different uses of a custom health rule you can use to poll your SharePoint farm for regular information or administrator warnings.
The following code illustrates how I created my health rule that checks for SharePoint features deployed on the server that are not packaged in a SharePoint solution package (WSP file). I list the built in features in a separate file I create, builtinfeatures.txt, and store in the Config directory in the SharePoint Root. Finally, I have included the feature activating and deactivating code to add/remove these health rules to the SharePoint farm.

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Text;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Health;
namespace Develops.SharePoint.HealthRule
{
    public class UnpackagedFeatureRule : SPHealthAnalysisRule
    {
        List<string> unpackagedFeatures = new
				List<string>();
        #region Properties
        public override string Summary
        {
            get { return "One or more custom features was deployed without packaging it in a SharePoint Solution Package."; }
        }
        public override string Explanation
        {
            get
            {
                StringBuilder builder = new StringBuilder();
                foreach (string feature in unpackagedFeatures)
                {
                    builder.AppendLine(feature);
                }
                return string.Concat(
                    "The following custom features were not associated with a SharePoint Solution Package: ", builder);
            }
        }
        public override string Remedy
        {
            get { return "Package the identified Features into SharePoint solution packages."; }
        }
        public override SPHealthCategory Category
        {
            get { return SPHealthCategory.Configuration; }
        }
        public override SPHealthCheckErrorLevel ErrorLevel
        {
            get { return SPHealthCheckErrorLevel.Warning; }
        }
        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                SPHealthAnalysisRuleAutomaticExecutionParameters retval = new SPHealthAnalysisRuleAutomaticExecutionParameters();
                retval.Schedule = SPHealthCheckSchedule.Monthly;
                retval.Scope = SPHealthCheckScope.All;
                retval.ServiceType = typeof(SPTimerService);
                return retval;
            }
        }
        #endregion
        #region Check
        public override SPHealthCheckStatus Check()
        {
            if (!SPFarm.Joined)
                throw new InvalidOperationException();
            List<string> systemFeatures = new List<string>();
            List<string> customFeatures = new List<string>();
            FileStream stream = new FileStream(
                SPUtility.GetGenericSetupPath(@"CONFIG") + @"\builtinfeatures.txt",
                FileMode.Open, FileAccess.Read);
            StreamReader reader = new StreamReader(stream);
            string line = reader.ReadLine();
            while (line != null)
            {
                systemFeatures.Add(line.ToLower(CultureInfo.CurrentCulture));
                line = reader.ReadLine();
            }
            reader.Dispose();
            stream.Dispose();
            SPFarm farm = SPFarm.Local;
            foreach (SPFeatureDefinition featureDef in farm.FeatureDefinitions)
            {
                if (featureDef.SolutionId.Equals(Guid.Empty) &&
                    !systemFeatures.Contains(featureDef.DisplayName.ToLower(CultureInfo.CurrentCulture)))
                {
                    unpackagedFeatures.Add(featureDef.DisplayName);
                }
            }
            if (unpackagedFeatures.Count == 0)
                return
				SPHealthCheckStatus.Passed;
            else
                return SPHealthCheckStatus.Failed;
        }
        #endregion
    }
}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration.Health;
namespace Develops.SharePoint.HealthRule.Features.HealthRules
{
    public class HealthRulesEventReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            Assembly a = Assembly.GetExecutingAssembly();
            IDictionary<Type, Exception> exceptions = SPHealthAnalyzer.RegisterRules(a);
        }
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            Assembly a = Assembly.GetExecutingAssembly();
            IDictionary<Type, Exception> exceptions = SPHealthAnalyzer.UnregisterRules(a);
        }
    }
} 

 

Advertisement
This entry was posted in SharePoint 2010 and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s