Archives

Archives / 2010 / November
  • Custom Health Rule for SharePoint 2010 that checks for Debug build assemblies

    Tags: SharePoint 2010

    Finally back in the blogging saddle, keep stacking ideas and post embryos but never time to finish them. This post is about how you create custom Health Rules for SharePoint 2010 and this health rule is of particular interest since it checks for debug build assemblies in all installed farm solutions.

    Health Rules

    Health Rules in SharePoint 2010 is a great way to make administrators aware of possible problems and issues with your farm; such as running out of disk space, living up to best practices etc. SharePoint 2010 comes with a bunch of out-of-the-box rules (of which some are good and some not that good). The best thing about the Health Rules is that you can write your own to fully satisfy your needs and live up to your governance standards.

    MSDN contains a guide on how to create these custom Health Rules in the "Developing and Deploying a Custom Health Rule" articles. Even though it covers the topic good it is not done using the Visual Studio 2010 SharePoint Developer Tools. This article actually uses MakeCab.exe and DDF files - like we did five years ago!

    I'm going to show you how to do it in a much easier way, but first something about the rule...

    Assemblies in Debug Mode

    This Health Rule that we are going to build will check all existing farm solutions for assemblies built in debug mode. Having assemblies built in debug mode in your production farm can severely hurt performance and even lock your processes down (think Assert dialogs on the server). I've seen debug builds on several production farms throughout the years (I have even put them there myself). It's kinda easy to miss to switch from Debug to Release when deploying a solution in a rush.

    Building the Health Rule

    So let's get to action and build our Health Rule. First of all you need Visual Studio 2010 and SharePoint Foundation 2010 or higher. Create a new Empty SharePoint project and select to deploy it as a farm solution. The Health Rule is implemented as a class, so go ahead and add a new class file to the project.

    First of all you need to derive the class from the SPHealthAnalysisRule:

    public class DebugAssemblies : SPHealthAnalysisRule

    Then you need to override a couple of methods and properties.

    The Summary property is the summary of the rule and is shown in Rule Definition (red box in image below):

    public override string Summary {
        get {
            return "One or more features contains assemblies built in Debug mode";
        }
    }

    Performance Rules

    The AutomaticExecutionParameters property defines the schedule and scope of the rule as well as if it should repair the "problem" automatically:

    public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters {
        get {
            SPHealthAnalysisRuleAutomaticExecutionParameters parameters = 
                new SPHealthAnalysisRuleAutomaticExecutionParameters { 
                    Schedule = SPHealthCheckSchedule.Daily, 
                    Scope = SPHealthCheckScope.Any, 
                    RepairAutomatically = false, 
                    ServiceType = typeof(SPTimerService) };
            return parameters;
        }
    }

    This rule is set to check for problems Daily and the checks should be done on any server where the Timer Service service is hosted. And no, we're not repairing this problem automatically

    The Category and ErrorLevel properties tells what category the rule ends up in and what severity a failed check causes:

    public override SPHealthCategory Category {
        get {
            return SPHealthCategory.Performance;
        }
    }
    public override SPHealthCheckErrorLevel ErrorLevel {
        get {
            return SPHealthCheckErrorLevel.Warning;
        }
    }

    For this rule we place it in the Performance category and only issue an warning when the check fails.

    The actual Health Rule check is done in the Check method, which we will look at in a second. First we define a custom class to store information about debug assemblies and a private property which contains all debug assembly information like this:

    List m_debuAssemblies = new List();
    class DebugAssembly{
        public string AssemblyName;
        public string SolutionName;
        public Guid SolutionId;
    }

    Now it's time to attack the Check method, which is the method that is executed when the rule is invoked. Here's the code for that one:

    public override SPHealthCheckStatus Check() {
        foreach (SPSolution solution in SPFarm.Local.Solutions) {
            // 1) Save file in temp
                    
            string tmp = System.IO.Path.GetTempPath();
            Guid guid = Guid.NewGuid();
            tmp = String.Format(@"{0}{1:D}\n", tmp, guid);
            System.IO.Directory.CreateDirectory(tmp);
    
            solution.SolutionFile.SaveAs(tmp + solution.Name);
    
            // 2) extract assemblies
            CabLib.Extract extractor = new CabLib.Extract();
            extractor.ExtractFile(tmp + solution.Name, tmp);
                    
            // 3) Open manifest
            NameTable nt = new NameTable();
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
            nsmgr.AddNamespace("sp", "http://schemas.microsoft.com/sharepoint/");
            XmlDocument manifest = new XmlDocument();
            manifest.Load(tmp + "manifest.xml");
    
            foreach(XmlNode assembly in 
                manifest.SelectNodes("//sp:Assemblies/sp:Assembly", nsmgr)){
    
                XmlElement elm = assembly as XmlElement;
                // 4) Inspect assembly
                if (IsDebugBuild(tmp + elm.GetAttribute("Location"))) {
                    m_debuAssemblies.Add(new DebugAssembly() { 
                        AssemblyName = elm.GetAttribute("Location"),
                        SolutionId = solution.Id,
                        SolutionName = solution.Name
                    });
                }
            }
        }
        // 4) Return
        if (m_debuAssemblies.Count == 0) {
            return SPHealthCheckStatus.Passed;
        }
        else {
            return SPHealthCheckStatus.Failed;
        }
    }

    What this method actually does it that it retrieves all farm solutions, copies the WSP to the temp directory and then uses CabLib.dll and extract all the files. Once the files are extracted it looks in the solution manifest for all assemblies and run the IsDebugBuild method to check if it is a debug build. All debug build assemblies are stored in the local property. Finally if it finds any debug assemblies it returns a failure message and if not it says that the rule was ok.

    To be able to compile this code you need to add a reference to Cablib.dll (x64) and also make sure that you include that assembly in your SharePoint Solution Package (Advanced tab in the Package editor)

    The IsDebugBuild method is a derivative of Scott Hanslemans old blog post "How to Programmatically Detect if an Assembly is Compiled in Debug or Release mode". Where I only changed it to return true or false.

    If the rule fails we need someway to inform the administrators. First we override the Remedy property which informs the administrators on how to act on this problem:

    public override string Remedy {
        get {
            return "Redeploy features built in Debug mode as Release builds";
        }
    }

    Then we also need to include some detailed explanation on what solutions and assemblies that causes this rule to fail. This is done using the Explanation property:

    public override string Explanation {
        get {
            StringBuilder sb = new StringBuilder();
            if (m_debuAssemblies.Count > 0) {
                sb.Append("The following assemblies are built in debug mode:\n");
                foreach (var assembly in m_debuAssemblies) {
                    sb.AppendFormat("Assembly {0} in solution {1}/{2},\n",
                        assembly.AssemblyName, assembly.SolutionName, assembly.SolutionId);
    
                }
                return sb.ToString();
            }
            else {
                return "No assemblies built in debug mode could be detected.";
            }
        }
    }

    This property retrieves all assemblies from the local property and writes a nice message for the administrators.

    Result of a failed Health Check rule

    Build the farm feature and register the rule

    Once we're finished with the rule we need to deploy it to our farm and register the rule with the Health Analyzer. Add a feature to your project and set the scope to farm. By default all farm features are Activated on Default - I prefer to change it to not activate on default and instead manually enable the feature in Central Admin. Add a feature receiver to your newly added feature and copy the FeatureActivated and FeatureDeactivated code from the MSDN article.

    Deploy and activate

    All is now ready for compilation, packaging and deployment. Do it! Then browse to Central Administration > System Settings > Manage Farm features and activate your feature:

    Activate!

    Your rule(s) should then appear in Central Administration > Monitoring > Review Rule definitions and you can (if you can't wait for it to automatically run) click on the rule and choose Run Now. Failed checks will appear in Monitoring > Review Problems and Solutions.

    Note: To debug your rule you need to attach the debugger to the OWSTimer.exe process - which is the timer service.

    Download

    If you think this rule is something that could be useful (and you should do), then download it here.

    Summary

    You've now seen how easy it is to implement and deploy a custom Health Rule. You should implement Health Rules that complies with your governance plans to make it easier and faster for the administrators and the governance-police.

  • About Cumulative Updates and Service Packs

    Tags: SharePoint, SQL Server, SharePoint 2010

    Yesterday the SharePoint Team posted on their blog about a major issue with the latest Cumulative Update for SharePoint 2010 and recommending not to install it. If you have installed it you might experience major problems with User Profile services - contact Microsoft Support as soon as possible for help.

    So what about these Cumulative Updates?

    imageEveryone that has been in the business for some time working with products such as SharePoint and other products such as SQL Server knows that the CU's are coming every each month or quarter. These updates contains the latest hotfixes assembled into a one package to make it easier for you to patch your server product. One problem with these CU's (not the actual CU's though) is that a lot of people download them and install them as soon as they are released - Fail! This is not the intended purpose of Cumulative Updates, let me explain why:

    Hotfixes

    Since the CU's contains of hotfixes, critical on-demand fixes and security fixes; some might already be available for download and some can only be reached through the Microsoft Support Services. A hotfix is intended to fix one or more specific bugs. The aim is to release a high-quality fix in an acceptable time frame - which in some cases might be a real issue. Sometimes there is not enough time to thoroughly test each hotfix for the wide diversity of environment and use-cases. One problem with the CU thing is that Microsoft also try to release them on a predictable schedule - this also means that there is not enough time to test.

    If you need to install a hotfix or a CU you must (just as you do with custom code or similar) test the installation before applying it to the production servers. One problem I've seen here is the lack of a test/staging environment where you can apply these hotfixes - if you do not have these environments - do not install the fixes! Even if you have a staging environment the best tip is to wait for a Service Pack, more about these later, or take it easy and listen (read Twitter, blogs etc.) for any issues. Oh, and how about making sure that you have a backup plan!

    KB articles

    For each and every hotfix Microsoft releases a set of Knowledge Base articles describing (almost) exactly what the hotfix is intended to fix. Before applying even the smallest hotfix - make sure that you read and understand the KB articles and also that you are experiencing the problems mentioned. If you do not experience them - there is no reason to apply the fix!

    The KB articles might not be ready when the CU/hotfix is published (back to the time frame issue). So wait until it is published and then read it. But still - only apply fixes that fix a problem you are having or if the CSS tells you to install it.

    Service Packs

    Sooner or later Microsoft bundles all CU's, hotfixes and optionally some new features together into a Service Pack. These are treated differently since most often there are more time to plan and test these. Service Packs are not flawless though. Same goes for all patching, updating, upgrading etc. - TEST, TEST and TEST!

    Been there, done that...

    I know I shouldn't throw stones in a glass house - I've been too trigger happy sometimes finding that a CU fixes one of my problems, installed it without testing enough and finally finding out that it only caused me more trouble on another end. Nevertheless I've learned my lesson...

    You can read more about the CU's in this KB article: http://support.microsoft.com/kb/953878

AWS Tracker

About Wictor...

Wictor Wilén is a Director and SharePoint Architect working at Connecta AB. Wictor has achieved the Microsoft Certified Architect (MCA) - SharePoint 2010, Microsoft Certified Solutions Master (MCSM) - SharePoint  and Microsoft Certified Master (MCM) - SharePoint 2010 certifications. He has also been awarded Microsoft Most Valuable Professional (MVP) for four consecutive years.

And a word from our sponsors...

SharePoint 2010 Web Parts in Action