How to create a monitor to inspect the value of a registry key

In my previous post similar to this topic, we discussed how to check for the existence of a registry key or value, and alert/change state if it was missing.  But what if you want to inspect the contents of a registry value for specific data?

For instance – what if we want to inspect a specific critical service, and ensure it is always set to “Automatic” startup?  Or perhaps we have a custom registry value that should always be set to a range of specific integers or string values, and we want to know if it exists, but it not set correctly?

This post will be an example of how to create a custom MonitorType to do that, very similar to how we did for existence.  I recommend starting with the previous post for greater details, as this article will leverage the same process.


Scenario:  We have a policy that we stamp the registry on all machines with the HKLM\Software\CompanyX key.  Within that Key – we have a Reg Value named “ServerLevel” which will be a number, 1 through 4.  Level 1 servers are critical production, level 2 servers are production, level 3 are pilot, and level 4 are development.  We use these values to dynamically assign these servers to custom groups in OpsMgr, for the purpose of scoping notifications, paging, and ticketing, as described HERE.  The goal of this monitor will be to ensure this value has been set, between 1 and 4.  The purpose is to ensure we don't have servers that are unset, as they will not get put into the appropriate group and we could miss some critical monitoring.


We want a monitor for this, and since no existing MonitorType exists – we will need to create one.


Create a new Empty Management Pack.


In your custom management pack, using the Authoring Console, create a new Composite MonitorType.


On the General tab – give the MonitorType a display name. 

(Custom - Check Existence of RegKey Monitor Type)

On the States tab – we need to define the state names we want.


On the Member modules tab:  We need to add 3 things for this example.  A datasource to the registry data we need, and two condition detections (one for good (RegValueBad) and one for bad (RegValueGood).

Click Add, and find the “Microsoft.Windows.RegistryProvider” Data Source.  In the ModuleID – this can be anything you want.  Most people just type DS (for DataSource).  I will type in “RegDS” for mine:


We used the Microsoft.Windows.RegistryProvider because this was a good existing Data Source module that has the ability to inspect the registry and has a schedule timer module as well.  To read about all the available modules, check out the TechNet Module Types Reference

On the RegDS Configuration – we have several items we need to input.

For ComputerName – change the default text to:  “$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$”  (no quotes)  This is a variable which will tell the workflow to connect to the local computer’s registry where it is running.  Described HERE

For AttributeName – this is just a text name to give the attribute of our Reg Key, I will call mine “ServerLevel” since that is the name of the Reg Value.  Described HERE

For Path – this is the path to the custom reg value.  HKLM is assumed – so you will need to add “SOFTWARE\CompanyX\ServerLevel”.  Described HERE

For PathType – this is “0” for a key, and “1” for a value.  We are inspecting a value in this case so ours will be “1”.  Described HERE

For Attribute Type – this is the data type to return to the workflow, we will use “1” – for String.  Generally – we want to match whatever the datatype is in the registry.  If the registry value was a REG_DWORD, we would use integer.  You can collect a string as an integer, but if ever an integer is not present, the workflow will not work and OpsMgr will throw an error.   The options are described HERE

For Frequency – we should input 86400 (this is seconds = 1 day). 

For testing in small labs you can set this to be more frequent, just be careful in production with aggressive monitoring on short frequencies.


That completes our datasource!  Next up – add two condition detections.

On the Member Modules tab, click Add, and add the System.ExpressionFilter.  Give our condition detection an ID at the bottom.  I will use “CDGood” for this one.


This condition detection type of System.ExpressionFilter is just a simple filter to be able to add conditional criteria to the output of our monitor type.

For the Expression of this Condition Detection, hit Configure.  Select “Insert”.  For the Parameter name – we need the name of the attribute we used in the data source.  We used “ServerLevel” so type that in here… but it MUST be prefaced with “Values/” so the final line to be added is “Values/ServerLevel”.  Since we want to make sure this is set to 1,2,3 or 4, we will use a regular expression.  For the value, we will use the simple regex of   ^(1|2|3|4)$     Click OK twice to accept our CD.


Now, back on the Member Modules tab, add another Condition Detection of the same type, but call this one “CDBad”.  We will configure this one identical to the above – but will set the Expression to “Values/ServerLevel” and “Does not match regular expression” and “^(1|2|3|4)$”.


On the Regular tab, we need to define the order or operations for each state.  On the “RegValueBad” we want the DataSource first, then the Condition Detection for “CDBad”, then output the module data.

Do the same thing for the RegValueGood state, but use the other condition detection for CDGood at the end of the workflow.


Click OK, and our MonitorType is done!


So – we have created our MonitorType.  Now we just need to create the monitor that will use this.  That part is a LOT easier.

Select the Health Model pane of the Authoring Console.

Select Monitors.  Right click > New > Custom Unit Monitor.

Give the Monitor an ID.  I chose “ExampleMP.ServerLevelConfiguredMonitor

Give the Monitor a good Display Name.  I chose “Custom - Monitor for ServerLevel setting in Registry

For the Target, I need this to run on all my Windows Servers, so I like to use “Microsoft.Windows.Server.OperatingSystem” (Windows Server Operating System).

For the Parent MonitorNEVER accept the default.  You always need to choose Availability, Configuration, Performance, or Security.  Since this is really a Configuration issue, I choose System.Health.ConfigurationState:




On the Configuration tab – we need to select a MonitorType for this monitor to use.  Click “Browse for a Type” and select the MonitorType we previously created.

On the Health tab – we need to define each operational state:


On the Alert tab – you can optionally create an alert when this monitor is in a warning Health state, and configure those typical items.

Click OK, and we are done!

You can now import this MP into your test/dev management group, and begin testing.  First – save your MP to a file for backup purposes.  Then, from the authoring console > Tools > Export MP to Management Group > Select your Dev MG, and the auth console with import this directly into it for quick testing.

This monitor will change to a Warning state if:

  • The reg value “ServerLevel” is missing.
  • The reg value exists but has no value set.
  • The reg value exists but is set to something other than the expected values.


You should see any Windows Server Operating System object that is missing that registry key, turn to a warning state.  This should be very clear in health explorer:




Example XML attached.


Comments (19)

  1. Kevin Holman says:

    Stay tuned to Jimmy Harpers blog – he is soon to publish a sample report that does exactly this!…/jimmyharper

  2. Kevin Holman says:

    Ryan – you still will want to use PS or VBscript and a propertybag…. if you need to do any complex calculations on the information you get from the registry, or need a monitor to inspect multiple keys/values…etc.  A script is still the simplest method when you need to do a lot of work.  This is just an example for when we just need something very simple, and I feel like there just arent enough examples out there of all the monitortype options.

  3. Kevin Holman says:

    Yes – that is planned for a future post.  This is 101 baby steps to get people used to creating their first monitortypes.  How to make custom monitortypes reuseable is one of my next posts.

  4. Nice demo, Kevin.  If someone wanted to make this MonitoringType more flexible and "reusable", we could expose configuration elements as input when creating the monitor(s) that will use this type, such as Regstry Path, Attribute Name, Path Type, Value and Frequency could be input during monitor creation.

  5. Kevin Holman says:

    Yikes – my bad.

    Your design is correct. I missed the concept that you want to know when the reg is missing! I need to slow down and read more sometimes! Sorry about that. I believe a single monitor like this will only work to tell you a BAD value and a MISSING value if you
    are using only a VALUE. If the entire Key hosting the value is missing, this may fail. I am not 100% sure on that, I’d have to test. In this case, I’d do two monitors – one for a missing value, and one for the incorrect value.

    If you cannot get it working – post the monitortype and monitor configuration from the XML here and we can take a look.

  6. Kevin Holman says:

    You should not be TARGETING servers with this monitor, that don’t have the registry key or value. That’s your first problem.

  7. ryan says:

    Nice Kevin.  This is probably much more efficient than my PS modules for reading the registry.  Never crossed my mind to use the builting registry provicer for anything other than simple discoveries.

  8. Andre Durval says:

    I make my own management pack to inspect a value of two registry key, but how can I create a report or a view to see all servers that have a bad value, instead of open each server in health explorer. ?!

  9. Jerry Nelson says:


    This is good stuff and very helpful for me as a noob to SCOM. Almost fits the bill for what I'm trying to accomplish, my hope is you can direct me to the steps necessary to return the discovered value to a column in the monitor view. For example: I have a software package that runs on 30 different Windows 2008 servers. Due to different system requirements some of these run different versions of an installed software package. I'm hoping to be able to get a registry probe that will check HKLMSOFTWAREProviderPackagePackageVersion and return the string value associated with that key in the format X.X.X.XXXXX

    Any ideas?

    Thanks and I am working through all your posts!

  10. cc60 says:

    Great post. Thanks

    It's possible in the System.ExpressionFilter make some like this:

    Operator: Contains

    Value: get-date -UFormat "%Y%m%d"

  11. OdgeUK says:

    Struggling with this. using it to monitor a Reg Value of Either "Stopped" or "Running" for "Current State" on some services which don’t appear as Windows Services (SCCM SMS Exec threads).

    Do you need the Values Prefix for a string match?

    I’m getting Healthy on the monitor, even on servers which don’t have the Key or Value?!

  12. OdgeUK says:

    Thanks Kevin. My Bad. I’m targeting Windows Server Operating System, and using overrides to enable this for two servers. one with the reg key present and in a status of running (so should be healthy) and another that does not have the reg key / value at
    all (which is also healthy). I am wondering if it should be "Value" instead of "Values" ? Or if I need this prefix at all when using a String for XpathQuery?

  13. OdgeUK says:

    May have misunderstood. Was expecting no Key / Value present to generate a Warning?

    This monitor will change to a Warning state if:
    •The reg value “ServerLevel” is missing.
    •The reg value exists but has no value set.
    •The reg value exists but is set to something other than the expected values.

  14. OdgeUK says:

    Great, that’s working now. Thanks for your reply Kevin. I can successfully monitor my Reg Value for a service. Healthy if = Running and Critical if NOT = Running (which covers missing value or unexpected values like "Stopping", or "Started" which should
    never exist for much more than a second or two).

    My issue was that when I used Explicit values for both Healthy ("= Running") and Critical ("= Stopped"), the monitor totally ignored anything else, including missing key, missing value or unexpected value. I was expecting the default behaviour to be a Warning
    under those conditions. Perhaps this is only when using Values and not Strings…

    How do I add meaningful Alert data in Alert Description? I want to have the output value in the Alert Description and / or Title. Do we need to have something like:

    $Data/Context/Context/DataItem/Current_State$ ?


    $Data/Context/Context/DataItem/Values$ ?

    This is the output in XML in the State Change detail:

    < DataItem type =" MOM.RegistryData " time =" 2015-04-26T19:00:05.7385374+01:00 " sourceHealthServiceId =" 8161FE81-FA5E-5187-42D1-351DFB963635 " >

    < Values >
    < Current_State VariantType =" 8 " > Running

  15. John says:

    Hey Kevin,

    I can’t seem to get this to work. Here is my code, the value I am checking is a DWORD and when it is 0 it is considered good, when it is 1 or higher it is considered bad. Here’s my code:!10894&authkey=!ADyX3DVPkUwOogw&ithint=file%2ctxt

  16. Joe says:

    For configuring the ComputerName in the Registry provider config, I had to remove the ‘Host’ in the string below:
    Changed to:

    The documentation states that the second form is used for windows-based computers.

    This was in a SCOM 2007 R2 environment, yes, I know it’s 2016… 🙂

    1. Kevin Holman says:

      Joe – if you had to remove the “host” this means you did a no-no and targeted Windows Computer.

      This is a known bad thing. My example targets windows operating system. No workflows should target Windows Computer.

  17. Andrius says:

    How do we to the same in SCOM 2012 R2? Because on 2012 R2 this tutorial breaks down at step 2: “In your custom management pack, using the Authoring Console, create a new Composite MonitorType.” <– there is no such thing there.

    1. Kevin Holman says:

      You would use the same tool as described above – which is the SCOM 2007 R2 Authoring tool –

      Or – you would use Visual studio and fragments:

Skip to main content