Monday, November 26, 2012

Enumerate SharePoint Solutions & Features for all Scopes

I have been involved in numerous custom SharePoint development projects, most of which are part of large SharePoint environments that have grown up over the course of many years.  Typically, multiple environments (production, integration, testing, etc) include hundreds of site collections, sites and sub-sites with SharePoint features activated at various scopes (farm, webapp, site collection and web). Determining which features are activated for a single site collection and site is relatively easy (although somewhat time-consuming) with the web interface:


However, what if you need a complete list of every built-in and custom feature (and associated solution) that is installed on a farm for every site collection and site and each feature's ID and activation scope?

This is quick command-line utility I created to provide these details. The complete Visual Studio 2010 project and source code is available for download at https://barkes@bitbucket.org/barkes/sharepoint-utilities.

SPEnumFeatures http://myserver/mysite false



The output can also be pipped to a CSV file from a command line and imported into Excel, for example:
SPEnumFeatures http://myserver/mysite false > features.csv


To Create the Command-line Utility in Visual Studio 2010

  1. Create a new project in Visual Studio named SPEnumFeatures by selecting the Console Application project template in the Visual C# category.

  2. Add a reference to the Microsoft.SharePoint assembly.  Right-click References in the Solution Explorer, select the Add Reference menu.  On the Add Reference dialog, select the .NET tab and locate the Microsoft.SharePoint (version 14.0.0.0) assembly and select the OK button.



  3. Open Program.cs and add the following code.
     Program.cs
    using System;
    using System.Collections.Generic;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    
    namespace Barkes.SharePoint.CmdLine
    {
        class SPEnumFeatures
        {
            // Solution Id to name dictionary.
            static Dictionary<Guid, string> ActiveSolutions = new Dictionary<Guid, string>();
            
            /// <summary>
            /// The output of this console app can be pipped to a CSV file from a command line and imported into Excel
            /// SPEnumFeatures http://myserver/mysite true > features.csv
            /// </summary>
            static void Main(string[] args)
            {
                if (args.Length == 2)
                {
                    // Get all solutions from the farm
                    SPSolutionCollection solutionsCollection = SPFarm.Local.Solutions;
                    foreach (SPSolution solution in solutionsCollection)
                    {
                        ActiveSolutions.Add(solution.Id, solution.DisplayName);
                    }
    
                    // Write the column headers
                    Console.WriteLine("{0},{1},{2},{3},{4},{5}",
                        "Url",
                        "Solution Name",
                        "Solution Id",
                        "Feature Name",
                        "Feature Id",
                        "Scope");
    
                    // Process features for all scopes (add a cmdline arg for scope designation in the future)
                    ProcessFeatures(args[0], Convert.ToBoolean(args[1]));
                }
                else
                {
                    WriteUsage();
                }
            }
    
            /// <summary>
            /// Show the command usage on the console.
            /// </summary>
            private static void WriteUsage()
            {
                Console.WriteLine();
                Console.WriteLine("Barkes SharePoint Utilities");
                Console.WriteLine();
                Console.WriteLine("SPEnumFeatures url showhidden [true|false]");
                Console.WriteLine();
                Console.WriteLine("SPEnumFeatures http://myserver/mysite false");
                Console.WriteLine();
                Console.WriteLine("The output of this console app can be pipped to a CSV file from a command line");
                Console.WriteLine("and imported into Excel, for example:");
                Console.WriteLine();
                Console.WriteLine("SPEnumFeatures http://myserver/mysite false > features.csv");
            }
    
            /// <summary>
            /// Retrieve and write the activated features.
            /// </summary>
            private static void ProcessFeatures(string baseUrl, bool showHidden)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    // Farm features
                    WriteActiveFeatures(@"Farm Global", SPWebService.ContentService.Features, showHidden);
    
                    using (SPSite entrySite = new SPSite(baseUrl))
                    {
                        // Web Application features
                        SPWebApplication webApp = entrySite.WebApplication;
                        WriteActiveFeatures(@"WebApp Global", entrySite.WebApplication.Features, showHidden);
    
                        SPSiteCollection siteCollections = webApp.Sites;
    
                        foreach (SPSite siteCollection in siteCollections)
                        {
                            // Site Collection features
                            WriteActiveFeatures(siteCollection.Url.ToString(), siteCollection.Features, showHidden);
    
                            SPWebCollection webCollection = siteCollection.AllWebs;
    
                            for (int i = 0; i < webCollection.Count; i++)
                            {
                                using (SPWeb web = webCollection[i])
                                {
                                    // Web features
                                    SPFeatureCollection webFeatures = web.Features;
                                    WriteActiveFeatures(web.Url, webFeatures, showHidden);
                                }
                            }
    
                            siteCollection.Close();
                        }
                    }
                });
            }
    
            /// <summary>
            /// Overload with default showOOTB = false
            /// </summary>
            private static void WriteActiveFeatures(string webUrl, SPFeatureCollection webFeatures,
                bool showHidden)
            {
                WriteActiveFeatures(webUrl, webFeatures, showHidden, false);
            }
    
            /// <summary>
            /// Write the features contained in the feature collection to the console.
            /// </summary>
            private static void WriteActiveFeatures(string webUrl, SPFeatureCollection webFeatures,
                bool showHidden, bool showOOTB)
            {
                foreach (SPFeature webFeature in webFeatures)
                {
                    try
                    {
                        SPFeatureDefinition webFeatureDefinition = webFeature.Definition;
                        Guid featureId = webFeatureDefinition.Id;
                        Guid solutionId = webFeatureDefinition.SolutionId;
    
                        // Skip the hidden features, if indicated
                        if (!showHidden && webFeatureDefinition.Hidden)
                            continue;
    
                        // Skip the built-in features, if indicated
                        if (!showOOTB && (featureId == Guid.Empty || solutionId == Guid.Empty))
                            continue;
                    
                        Console.WriteLine("{0},{1},{2},{3},{4},{5}",
                            webUrl,
                            ActiveSolutions[webFeatureDefinition.SolutionId],
                            webFeatureDefinition.SolutionId,
                            webFeatureDefinition.DisplayName,
                            webFeatureDefinition.Id,
                            webFeatureDefinition.Scope.ToString());
                    }
                    catch (Exception)
                    {
                        ; // Do nothing
                    }
                }
            }
        }
    }
    

No comments:

Post a Comment