by Marcin Policht
Virtually every single person using any of the operating systems from the
Windows family has to resort, at some point, to making configuration
changes via direct registry access (instead of using the more “friendly” and
Microsoft-recommended GUI-based tools). Typically, such changes are
performed with considerable caution and a strict following of the directions contained in one
of the Microsoft knowledge base articles (which always include the standard
disclaimer about dangers associated with such procedures).
In his latest article, Marcin Policht takes a look at some of the limitations in the Windows Script Host and illustrates the use of the WMI Standard Registry Provider to get around many of them.
In order to minimize your risks when dealing with the registy, you can use
scripting. This way, you’re able to protect yourself against accidental typos, and you also enjoy
the additional significant benefit of being able to automate registry modifications, which becomes a very important factor when dealing
with larger environments.
Microsoft provides a means of accomplishing this goal in several ways. The
most popular tool is the Windows Script Host. Its most recent version, 5.6,
is built into Windows XP and offers the long-awaited ability to run scripts remotely.
However, despite its well-documented syntax and relative ease of use, its
registry methods are still lacking some functionality. Most notably, the RegRead
(for registry reading) and RegWrite (for registry writing) methods do not
work with multi-string registry entries, and RegWrite support for binary
entries is limited to values in the range of four bytes. It is also fairly
difficult to enumerate subkeys or entries within a registry key. Finally,
none of the methods of Windows Script Host can be used to deal in any way
with registry permissions.
All these limitations can be eliminated with WMI Standard Registry
Provider, which is built into Windows XP and is also available as an add-on for Windows NT and
2000. The Standard Registry Provider offers the following methods:
- GetBinaryValue – reads regisry value of BINARY type
- GetDWORDValue – reads registry value of DWORD type
- GetExpandedStringValue – reads registry value of EXPANDED STRING type
- GetMultiStringValue – reads registry value of MULTI STRING type
- GetStringValue – reads registry value of STRING type
- CreateKey – creates registry key
- SetBinaryValue – writes registry value of BINARY type
- SetDWORDValue – writes registry value of DWORD type
- SetExpandedStringValue – writes registry value of EXPANDED STRING
type - SetMultiStringValue – writes registry value of MULTI STRING type
- SetStringValue – writes registry value of STRING type
- DeleteKey – deletes registry key
- DeleteValue – deleting registry value
- EnumKey – enumerates registry key
- EnumValues – enumerates registry value
- CheckAccess – checks permissions on registry key
In this article, I’ll present implementation of some of these methods.
As usual, we will start with defining constants. Five of them will
correspond to the registry trees, viewed in REGEDIT.EXE as top level
folders.
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_CURRENT_CONFIG = &H80000005
The StdRegProv class, which all the listed previously methods are a part of,
resides in rood/default WMI namespace. This means that in our scripts
we will first need to connect to this namespace (and the StdRegProv class
within it). The most straightforward way of performing this step is by using
so-called moniker notation.
Set oRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
sComputer & "/root/default:StdRegProv")
where sComputer is the variable containing the name of the target
computer.
Next, we need to create an object corresponding to the method being
invoked. This is done using the following syntax:
Set oMethod = oRegistry.Methods_(sMethod)
where sMethod contains the name of the method (from the list
above).
Depending on the method, one or more additional parameters might be
required. These parameters are stored in an additional object we create called oInParam).
Set oInParam = oMethod.inParameters.SpawnInstance_()
This is followed by setting different parameters that are part of
the oInParam object. For example:
oInParam.hDefKey = HKEY_CURRENT_USER
where HKEY_CURRENT_USER is one of the previously defined constants.
In order to execute the method, we need to call ExecMethod_ method of
oRegistry object, which takes two arguments — the name of the method
(stored in sMethod variable) and the object containing all input
parameters (called by us oInParam). This is done with the following
line:
Set oOutParam = oRegistry.ExecMethod_(sMethod, oInParam)
The result of calling the method can be retrieved by checking the content
of oOutParam object.
The best way to get familiar with the described process is by looking at
examples. Here is the way to read a string value from the registry — in this
case, we want to retrieve the value of :
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_CURRENT_CONFIG = &H80000005
sComputer = "TargetComputer"
sMethod = "GetStringValue"
hTree = HKEY_LOCAL_MACHINE
sKey = "SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon"
sValue = "DefaultUserName"
Set oRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
sComputer & "/root/default:StdRegProv")
Set oMethod = oRegistry.Methods_(sMethod)
Set oInParam = oMethod.inParameters.SpawnInstance_()
oInParam.hDefKey = hTree
oInParam.sSubKeyName = sKey
oInParam.sValueName = sValue
Set oOutParam = oRegistry.ExecMethod_(sMethod, oInParam)
WScript.Echo oOutParam.Properties_("sValue")
The same script can be used to read registry values of type multi-string
and expanded-string (just remember to change the value of sMethod
variable to “GetMultiStringValue” or “GetExpandedStringValue” and point to
appropriate registry key and value). Also, note that you need to set the
value of sComputer to match the actual name of the target computer. You
can use single dot (“.”) when referring to the local system.
Retrieving binary value from the registry will be done almost
identically. The obvious change is the new value of the sMethod
variable (since we are calling the “GetBinaryValue” method) as well as the
registry key and value. Another, less obvious change is the way the results
are retrieved. The binary value is returned as “uValue” property (unlike
“sValue” property from the previous example). “uValue” property is an array
of bytes, each displayed in decimal format (a value between 0 and 255).
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_CURRENT_CONFIG = &H80000005
sComputer = "TargetComputer"
sMethod = "GetBinaryValue"
hTree = HKEY_LOCAL_MACHINE
sKey = "SOFTWAREMicrosoftWindows NTCurrentVersion"
sValue = "DigitalProductId"
Set oRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}//" & _
sComputer & "/root/default:StdRegProv")
Set oMethod = oRegistry.Methods_(sMethod)
Set oInParam = oMethod.inParameters.SpawnInstance_()
oInParam.hDefKey = hTree
oInParam.sSubKeyName = sKey
oInParam.sValueName = sValue
Set oOutParam = oRegistry.ExecMethod_(sMethod, oInParam)
For iCount = 0 To UBound(oOutParam.Properties_("uValue"))
WScript.Echo oOutParam.Properties_("uValue")(iCount)
Next
The same script can be used to read the registry value of DWORD type
(after changing value of the sMethod variable to GetDwordValue and
specifying appropriate registry key and value).
In the next article of this series I’ll present other methods of the
StdRegProv class.