System Center Operations Manager (SCOM) Overrideable Parameters Listing Tool

This article is about a System Center Operations Manager (SCOM) tool that I created for listing the overrideable parameters available in a particular Management Pack. The tool outputs an HTML document containing a table of all discoveries, rules and unit monitors in the specified Management Pack with their associated overrideable parameters.

Here are a few scenarios where this tool might be useful:

  • You would like to understand in detail the configuration options for a vendor supplied management. Since the overrideable parameters are the primary means for configuring a management pack, this information can provide useful insights into how to tune a management pack for a specific environment.
  • You want to provide detailed documentation for a custom developed management pack to your customer. The output of this tool can be easily incorporated into the documentation you provide with your management pack.
  • You are looking for sample code that shows how to access management pack objects.

This tool requires a connection to the Management Group where the management pack is imported.

The tool is a simple command line program. It takes three arguments. The first specifies the management server (use "localhost" if running the command on the server). The second is the management pack name, and the third is the output file name.

For example:

GetOverrideableParameters.exe localhost Microsoft.SQLServer.2000.Monitoring c:\SqlMonitoringParamerts.html

Download the tool and the Visual Studio project from the links provided at the end of this article.

Implementation Details

The program is written in C# and was developed using Visual Studio 2010. It has been successfully used in a System Center Operations Manager R2 deployment.

The program references SCOM .Net assemblies Microsoft.EnterpriseManagement.OperationsManager and Microsoft.EnterpriseManagement.OperationsManager.Common. It should run on computers where the Operations Console has been installed.

The generated HTML is very basic and should be easy to enhance either through extension of the program or via direct editing in an HTML editor. The generated HTML consists of a table of parameters.  It is also straight forward to copy / paste this HTML from the browser into a Word document for more extensive formatting.

The program flow is as follows:

  • - Connect to the management group
  • - Get the Management Pack object
  • - Emit the HTML header info
  • - Loop through all Discoveries in the management pack and emit the overrideable parameters for each.
  • - Loop through all Rules in the management pack and emit the overrideable parameters for each.
  • - Loop through all UnitMonitors in the management pack and emit the overrideable parameters for each.
  • - Emit the closing tags for the HTML
  • - Close the output file

Note that the reason this program must connect to the Management Group is because the resolution of datasource information requires access to management packs referenced by the specified management pack.

Also note that the "Value" column displayws in the output file shows the parameter value as configured in the Management Pack. It does not reflect any overrides that may be in effect.

You can download a zip file containing the executable for the program from here: https://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-03-40-SCOM+Overrideable+Parameters/8345.GetOverrideableParametersExecutable.zip

You can download a zip file containing the Visual Studio project from here: https://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-03-40-SCOM+Overrideable+Parameters/1004.GetOverrideableParametersProject.zip

You can download a sample of the program output here: https://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-03-40-SCOM+Overrideable+Parameters/6675.sample.html

Here is a listing of the main program:

using System;

using System.Text;

using System.Collections.Generic;

using Microsoft.EnterpriseManagement;

using Microsoft.EnterpriseManagement.Common;

using Microsoft.EnterpriseManagement.Administration;

using Microsoft.EnterpriseManagement.Configuration;

using System.Collections.ObjectModel;

using System.IO;

using System.Xml;

 

namespace GetOverrideableParameters

{

    class Program

    {

        static void Main(string[] args)

        {

            if (args.GetLength(0) != 3)

            {

                Console.WriteLine("Error: Unexpected commandline argument count. Usage: GetOverrideableParameters <Management Group server name> <MP name> <outputfile>");

                System.Environment.Exit(1);

            }

 

            ManagementPack mp = null;

            ManagementGroup mg = null;

 

            try

            {

                mg = new ManagementGroup(args[0]);

            }

            catch (System.Exception excp)

            {

                Console.WriteLine("Error: Could not connect to management group: {0}", excp.Message);

                System.Environment.Exit(1);

            }

 

            try

            {

                mp = mg.GetManagementPacks(args[1])[0];

            }

            catch (System.Exception excp)

            {

                Console.WriteLine("Error: Could not get management pack: {0}", excp.Message);

                System.Environment.Exit(1);

            }

 

            ManagementPackElementCollection<ManagementPackRule> rules = mp.GetRules();

            ManagementPackElementCollection<ManagementPackMonitor> monitors = mp.GetMonitors();

            ManagementPackElementCollection<ManagementPackDiscovery> discoveries = mp.GetDiscoveries();

 

            StreamWriter writer = null;

 

            try

            {

                writer = new StreamWriter(args[2]);

            }

            catch (System.Exception excp)

            {

                Console.WriteLine("Error: Could not create output file: {0}", excp.Message);

                System.Environment.Exit(1);

            }

 

            // Output preamble for HTML document

            writer.WriteLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");

            writer.WriteLine("<html xmlns=\"https://www.w3.org/1999/xhtml\" >");

            writer.WriteLine("<head>");

            writer.WriteLine("<title>Untitled Page</title>");

            writer.WriteLine("</head>");

            writer.WriteLine("<body>");

 

            writer.WriteLine("<h1>{0} Overrideable Parameters</h1>", mp.DisplayName == null ? mp.Name : mp.DisplayName);

 

            // Start the table and emit a header line

            writer.WriteLine("<table style=\"width: 100%;\" border=\"2\" >");

            writer.WriteLine("<tr><td>Monitoring Object</td><td>Parameter</td><td>Description</td><td>Value</td></tr>");

 

            foreach (ManagementPackDiscovery discovery in discoveries)

            {

                ManagementPackDataSourceModuleType datasourceType = (ManagementPackDataSourceModuleType)mg.GetMonitoringModuleType(discovery.DataSource.TypeID.Id);

 

                EmitOverrideableParameters(discovery.DisplayName != null ? discovery.DisplayName : discovery.Name, writer, discovery.DataSource.Configuration, datasourceType.OverrideableParameterCollection);

            }

 

            foreach (ManagementPackRule rule in rules)

            {

                string ruleName = rule.DisplayName != null ? rule.DisplayName : rule.Name;

 

                foreach (ManagementPackDataSourceModule datasource in rule.DataSourceCollection)

                {

                    ManagementPackDataSourceModuleType datasourceType = (ManagementPackDataSourceModuleType)mg.GetMonitoringModuleType(datasource.TypeID.Id);

 

                    EmitOverrideableParameters(ruleName, writer, datasource.Configuration, datasourceType.OverrideableParameterCollection);

 

                    ruleName = ""; // We only want the name to display on the first row emitted for this rule.

                }

            }

 

            foreach (ManagementPackMonitor monitor in monitors)

            {

                if (monitor is ManagementPackUnitMonitor)

                {

                    ManagementPackUnitMonitor unitMonitor = (ManagementPackUnitMonitor)monitor;

 

                    UnitMonitorType unitMonitorType = mg.GetUnitMonitorType(unitMonitor.TypeID.Id);

 

                    EmitOverrideableParameters(unitMonitor.DisplayName != null ? unitMonitor.DisplayName : unitMonitor.Name, writer, unitMonitor.Configuration, unitMonitorType.OverrideableParameterCollection);

                }

            }

 

            writer.WriteLine("</table>");

            writer.Close();

 

            Console.WriteLine("All done!");

        }

 

        /// <summary>

        /// Emit the HTML for a collection of overrideable parameters.

        /// </summary>

        /// <param name="Named"></param>

        /// <param name="Name"></param>

        /// <param name="writer"></param>

        /// <param name="Configuration"></param>

        /// <param name="OverrideableParameterCollection"></param>

        private static void EmitOverrideableParameters(string Name, StreamWriter writer, string Configuration, ManagementPackSubElementCollection<ManagementPackOverrideableParameter> OverrideableParameterCollection)

        {

            // Load the config section into an XML document for use in looking up actual values.

            XmlDocument xmlConfig = new XmlDocument();

            xmlConfig.LoadXml("<root>" + Configuration + "</root>");

 

            bool firstRow = true;

 

            foreach (ManagementPackOverrideableParameter op in OverrideableParameterCollection)

            {

                writer.WriteLine("<tr>");

 

                // rule name

                writer.Write("<td>");

 

                if (firstRow)

                {

                    // Display object name only on the first row for this object.

                    writer.Write(Name);

                    firstRow = false;

                }

 

                writer.WriteLine("</td>");

 

                // Parameter name

                writer.Write("<td>");

                if (op.DisplayName == null)

                    writer.Write(string.Format("{0}", op.Name));

                else

                    writer.Write(string.Format("{0}", op.DisplayName));

                writer.WriteLine("</td>");

 

                // Parameter description

                writer.Write("<td>");

 

                if (op.Description == null)

                    writer.Write(string.Format(""));

                else

                    writer.Write(string.Format("{0}", op.Description));

                writer.WriteLine("</td>");

 

                // Get the parameter Value. This gets the value from the configuration in the MP. It does not take into account overrides.

                writer.Write("<td>");

                XmlNodeList nodes = xmlConfig.GetElementsByTagName(op.Name);

                if (nodes.Count > 0)

                    writer.Write(XMLEncode(nodes[0].InnerXml));

 

                writer.WriteLine("</td>");

 

                writer.WriteLine("</tr>");

            }

        }

 

        /// <summary>

        /// Helper function for encoding strings to be embedded in XML

        /// </summary>

        /// <param name="Value"></param>

        /// <returns></returns>

        private static string XMLEncode(string Value)

        {

            return Value.Replace("&", "&amp;").Replace("'", "&apos;").Replace("\"", "&quot;").Replace("<", "&lt;").Replace(">", "&gt;");

        }

 

    }

 

 

}