This is based on an idea I had to help improve the registry inventory capabilities of Hardware Inventory. The idea was inspired by Mark Cochrane’s RegkeyToMof tool, as well as from some advice from Sherry Kissinger. There was also a thread on the mssms list where people suggested improvements for ConfigMgr, and I suggested Registry Inventory.
The concept is to put multiple ad hoc registry values into the Hardware Inventory. The common way of doing this was to add multiple values into a single instance. In Resource Explorer this displays as a single row with multiple columns. I found this a bit too unwieldy after a while.
My idea was to try to effectively pivot this data round so that you had multiple rows, with minimal columns.
I simply felt scrolling vertically was nicer than scrolling horizontally. I also like the idea of having the full registry path in the Resource Explorer view.
Here is how I achieved this.
Addition to SMS_DEF.MOF (Note. This part never needs to change)
//`'`*._.*`'`*-
// Registry_Values Reporting Class
//`'`*._.*`'`*-
#pragma namespace("\\\\.\\ROOT\\CIMV2\\SMS")
#pragma deleteclass("Registry_Values",NOFAIL)
[ SMS_Report (TRUE),
SMS_Group_Name ("Registry_Values"),
SMS_Class_ID ("CUSTOM|Registry_Values|1.0")
]
Class Registry_Values : SMS_Class_Template
{
[SMS_Report(TRUE),key] string KeyName; // The registry value name
[SMS_Report(TRUE)] string String; // For REG_SZ or REG_EXPAND_SZ values
[SMS_Report(TRUE)] string Multi[]; // For REG_MULTI_SZ values
[SMS_Report(TRUE)] Uint64 Integer; // For REG_DWORD values
};
Addition to CONFIGURATION.MOF
//`'`*._.*`'`*-
// Registry_Values Data Class
//`'`*._.*`'`*-
#pragma namespace("\\\\.\\ROOT\\CIMV2")
#pragma deleteclass("Registry_Values",NOFAIL)
[DYNPROPS]
Class Registry_Values
{
[key] string KeyName=""; // The registry value name
String String; // For REG_SZ or REG_EXPAND_SZ values
String Multi[]; // For REG_MULTI_SZ values
Uint64 Integer; // For REG_DWORD values
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon|AltDefaultUserName";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon|AltDefaultUserName")
,Dynamic,Provider("RegPropProv")] String;
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon|DefaultUserName";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon|DefaultUserName")
,Dynamic,Provider("RegPropProv")] String;
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Installer|Logging";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Installer|Logging")
,Dynamic,Provider("RegPropProv")] String;
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SMS\\Client\\Client Components\\Remote Control|Permission Required";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SMS\\Client\\Client Components\\Remote Control|Permission Required")
,Dynamic,Provider("RegPropProv")] Integer;
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SMS\\Client\\Client Components\\Remote Control|PermittedViewers";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SMS\\Client\\Client Components\\Remote Control|PermittedViewers")
,Dynamic,Provider("RegPropProv")] Multi;
};
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\VBSFile\\Shell\\Open\\Command|";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\VBSFile\\Shell\\Open\\Command|")
,Dynamic,Provider("RegPropProv")] String;
};
-----------------------
If you look at the addition to SMS_DEF.MOF, this never needs to change.
However, to report multiple values is simply a matter of adding an extra “[DYNPROPS] instance of Registry_Values...” section into CONFIGURATION.MOF. Let’s take a look at one section to get an idea of the syntax.
-----------------------
[DYNPROPS]
instance of Registry_Values
{
KeyName="HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Installer|Logging";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows\\Installer|Logging")
,Dynamic,Provider("RegPropProv")] String;
};
-----------------------
I’ve indented the “KeyName=...” line, so you can compare it with the “[PropertyContext...” line. You should be able to see that they are the same from HKEY_LOC... through to Logging".
The backslash is a special character, hence to reference a backslash, you need to use “\\”. The text after “|” is the value’s name. For (Default) values, there is no text after the “|”, as the last example shows ( i.e. KeyName="HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\VBSFile\\Shell\\Open\\Command|"; )
On the last line before the “};”, there are three possibilities, depending on the type of value being inventoried.:-
-----------------------
,Dynamic,Provider("RegPropProv")] String; // For REG_SZ or REG_EXPAND_SZ values
or
,Dynamic,Provider("RegPropProv")] Multi; // For REG_MULTI_SZ values
or
,Dynamic,Provider("RegPropProv")] Integer; // For REG_DWORD values
-----------------------
I hope this is fairly self explanatory, and is useful for creating your own ad hoc registry inventorying.