Chapter 16. Registry

The registry is an integral part of the Microsoft® Windows® 2000 operating system, containing configuration settings for both the operating system and the applications and services that run under Windows. Scripts that use the Windows Management Instrumentation (WMI) Registry Provider offer a flexible solution for managing the registries of computers across an enterprise.

In This Chapter

Registry Overview

The registry is the centralized configuration database for the Windows operating system and for applications and services running under Windows. As such, it plays a vital role as the repository for computer system configuration data. The registry stores a wide range of configuration settings, from boot parameters to user desktop settings. Because these settings play a crucial role in determining how — and sometimes even if — a computer runs, managing the registry is an important aspect of Windows system administration.

You might not be aware of it, but if you manage Windows-based systems you spend a significant amount of your time reading and modifying settings in the registry. Many of the Control Panel applets, command-line tools, and Microsoft Management Console (MMC) plug-ins that you use each day perform some of their functions by reading, changing, or adding registry subkeys or entries. These tools offer a more user-friendly interface for working with the registry and provide a safeguard against misconfiguring a registry value. When you use these tools, you might not be aware that you are actually modifying the registry.

In most cases, you can use system tools to indirectly modify registry settings. However, occasionally you need to work with the registry directly, especially if you do not have system tools available that can manage those settings across an enterprise. When you need to manage registry settings across an enterprise and no system tool is available to do this, you can use scripts that leverage the WMI Registry Provider.

Note

Note

Windows Script Host also provides methods for working with the registry. However, these methods represent only a subset of the capabilities found in the Registry Provider. In addition, the Registry Provider makes it as easy to work with the registry on a remote computer as it does to work with the registry on the local computer. WSH, by contrast, is designed to work only on the local computer.

Regardless of whether you use the registry editors or a script, when you edit the registry directly, you must determine which entries or subkeys to modify and how to modify them. In contrast, if you use a system tool to modify the entries or subkeys, the tool will determine which items you can modify and will ensure that you can make only valid modifications. For example, if only 0 and 1 are valid values for a registry entry, these tools will typically not allow you to set the value of the entry to 2 or 3. Before you decide to write a script or otherwise edit the registry directly, research the use of the following configuration management alternatives:

  • Group Policy

  • Scriptable COM objects

  • Command-line tools

Given how critical the registry is to the proper functioning of the operating system and your applications, it is imperative that you back it up regularly. You should be especially diligent about backing up the registry immediately before editing it — directly or indirectly.

This chapter demonstrates how to use the WMI Registry Provider in your scripts to automate the examination, modification, and deletion of subkeys and entries in the registry. The chapter does not explain the meaning and effect of the various entries in the registry. To make use of the scripting techniques demonstrated, you must already be knowledgeable about certain subkeys or entries. Otherwise, begin by consulting a reliable source of information such as the Registry Reference on the Microsoft Windows 2000 Server Resource Kit companion CD, or on the Web at http://www.microsoft.com/reskit.

The Registry Reference contains detailed information about where in the registry specific configuration settings are stored, what values the settings can have, and what the values mean. The Registry Reference also includes a “Change Method” section for many of the entries; these sections describe system tools that manage the entry so that you can avoid editing it directly.

Caution

Caution

Changing the registry with a script can easily propagate errors. The scripting tools bypass safeguards, allowing settings that can damage your system, or even require you to reinstall Windows. Before scripting changes to the registry, test your script thoroughly and back up the registry on every computer on which you will make changes. For more information about scripting changes to the registry, see the Registry Reference on the Windows 2000 Server Resource Kit companion CD or at http://www.microsoft.com/reskit.

Registry Editor

The registry editors Regedit.exe and Regedt32.exe are the GUI-based system tools for managing the registry. They present a view of the registry that looks similar to the Windows Explorer view of the file system.

Although you can use the registry editors to connect to and manage the registry on a remote computer, they do not provide an easy way to make the same changes across multiple registries. If you need to make such enterprise-wide changes, you should first investigate other means, such as Group Policy. If you find no other alternative, try scripts like the ones presented in this chapter.

Caution To open the registry editor Regedit.exe

  • In the Run dialog box, type regedit, and then click OK.

Figure 16.1 shows the registry editor Regedit.exe.

Registry Editor Regedit.exe

Figure 16.1. Registry Editor Regedit.exe

Note

Note

In Windows 2000, there are two registry editors Regedit.exe and Regedt32.exe. Each provides a different view of the information in the registry and includes useful features not available in the other. Regedit.exe, for instance, provides powerful search capabilities, while Regedt32.exe enables the viewing and changing of access permissions.

Registry Structure

The registry, as it appears in Regedit.exe, has a hierarchical organization. Figure 16.2 identifies the elements in the hierarchy as they are displayed in the registry editors: subtrees, keys, subkeys, and the components of a registry entry. This hierarchy looks similar to the system drive letters, folders, and subfolders you find in Windows Explorer.

Registry Elements

Figure 16.2. Registry Elements

When you view the registry in a registry editor, you see the hierarchy in a tree control in the left section of the window and the registry entries in the right section of the window. When you are using a registry editor, you typically navigate through the keys and subkeys of a given subtree until you find the entry you are interested in and then edit that entry. You rarely need to edit the subkeys themselves.

Subtrees

Subtrees make up the first or root level of the registry hierarchy. If you compare the elements of the registry hierarchy to the elements of the file system hierarchy, registry subtrees correspond to file system drive letters. Each subtree contains a particular category of keys, subkeys, and entries. The HKEY_LOCAL_MACHINE subtree, for instance, contains computer-specific settings, while the HKEY_CURRENT_USER subtree contains user-specific settings. Many of the changes you make to the registry involve entries contained within one of these two subtrees.

Table 16.1 lists all the subtrees in the registry along with descriptions and commonly used abbreviations. (In registry documentation, for example, you will typically see HKEY_CURRENT_USER referred to as HKCU.)

Table 16.1. Registry Subtrees

Subtree

Description

Abbreviation

HKEY_CLASSES_ROOT

Symbolic link to HKEY_LOCAL_MACHINE SOFTWAREClasses

Clicking on the HKEY_CLASSES_ROOT subtree takes you to the same place you would reach by navigating to HKEY_LOCAL_MACHINESOFTWAREClasses

HKCR

HKEY_CURRENT_USER

Symbolic link to a key under HKEY_USERS representing the current user

HKCU

HKEY_LOCAL_MACHINE

Information about the local computer

HKLM

HKEY_USERS

Information about users

HKU

HKEY_CURRENT_CONFIG

Symbolic link to the key of the current hardware profile under

HKEY_LOCAL_MACHINESYSTEMCurrentControlSet ControlIDConfigDBHardware Profiles

HKCC

HKEY_PERFORMANCE_DATA

Information about performance. Not accessible using the registry editors

No commonly used abbreviation

Keys and subkeys

Keys make up the second level of the registry hierarchy. They correspond to top-level folders located in the root directory of a file system. Keys can contain other folder-like elements known as subkeys. Keys do not normally contain registry entries other than the default entry (to be discussed later in this chapter).

Subkeys are analogous to subfolders. They can contain other subkeys as well as registry entries.

Entries

Registry entries correspond to files in a file system. Unlike subtrees, keys, and subkeys, entries are designed to store configuration data, not to categorize it. An entry consists of a name, a data type (which defines the length and format of data that the entry can store), and a field known as the value of the entry. Configuration data is stored in the value field of a registry entry.

Table 16.2 lists all of the data types that can be used in registry entries. The first four are the ones most commonly used in scripts.

Table 16.2. Registry Entry Data Types

Data Type

Description

REG_SZ

A string (series of characters) that ends with a null character. Strings that end with a null character are known as null-terminated strings. The Z in REG_SZ refers to the null (or zero) character.

REG_DWORD

A number that can range from 0 to 4,294,967,295.

DWORD refers to the fact that 32 bits are allocated for storing the value. Because 16 bits of storage space is known as a word, 32 bits is known as a double word (DWORD).

REG_MULTI_SZ

An array of null-terminated strings that is itself terminated by two successive null characters. This enables you to store multiple values in a single registry entry, similar to the way arrays enable you to store multiple values within a single variable.

REG_EXPAND_SZ

A null-terminated string that contains unexpanded references to environment variables (%PATH%, for example).

REG_BINARY

Binary data in any form.

REG_DWORD_LITTLE_ENDIAN

A number that can range from 0 to 4,294,967,295 and is stored in a format known as little-endian. (Little-endian means that the most significant byte is located on the right end of the word.)

REG_DWORD_BIG_ENDIAN

A 32-bit number in big-endian format. (Big-endian means that the most significant byte is located on the left end of the word.)

REG_QWORD

A 64-bit number.

REG_QWORD_LITTLE_ENDIAN

A 64-bit number in little-endian format (same as REG_QWORD).

REG_RESOURCE_LIST

A device driver resource list.

REG_FULL_RESOURCE_DESCRIPTOR

A list of hardware resources that a physical device is using. The system detects the resources and writes the list into the HardwareDescription tree.

REG_RESOURCE_REQUIREMENTS_LIST

A device driver’s list of possible hardware resources that it or one of the physical devices it controls can use. The system writes a subset of this list into the ResourceMap tree.

REG_LINK

A Unicode symbolic link. Used internally; not used by applications.

REG_NONE

No defined value type.

Each registry subtree, key, and subkey has a default entry. Default entries are of the string data type, which is denoted REG_SZ. If a default entry does not contain a value, a registry editor displays the value as (value not set). When you create a subkey, a default entry with (value not set) is automatically added. You can change the value of the default entry using the methods of the Registry Provider. Note that, in contrast, the RegWrite method of the WshShell object does not allow you to modify the value of the default entry.

Registry files

The registry is composed of several sources of data. These sources include some of the files in the folder systemrootSystem32config. Each file that houses some portion of the registry is known as a hive. The list of hive files is stored in the registry itself.

Note

Note

The registry editors hide some portions of the registry, including a subtree related to performance counters. These items are not accessible because you should never directly modify them. Incorrectly configuring these values could seriously degrade the performance of your computer.

Listing 16.1 contains a script that displays the locations of the registry hive files. It retrieves the information from registry entries in the HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlhivelist subkey. The techniques used in this script are explained later in this chapter.

Example 16.1. Listing the Files That Make Up the Registry

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6 strKeyPath = "SystemCurrentControlSetControlhivelist"
 7 objReg.EnumValues HKEY_LOCAL_MACHINE, strKeyPath, _
 8     arrValueNames, arrValueTypes
 9
10 For i=0 To UBound(arrValueNames)
11     Wscript.Echo "File Name: " & arrValueNames(i)
12     objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
13         arrValueNames(i),strValue
14     Wscript.Echo "Location: " & strValue
15 Next

When the preceding script runs under CScript on a Microsoft® Windows® 2000 Professional–based computer, information similar to the following appears in the command window:

File Name: REGISTRYMACHINESECURITY
Location: DeviceHarddiskVolume1WINDOWSsystem32configSECURITY
File Name: REGISTRYMACHINESOFTWARE --
Location: DeviceHarddiskVolume1WINDOWSsystem32configSOFTWARE
File Name: REGISTRYMACHINESYSTEM
Location: DeviceHarddiskVolume1WINDOWSsystem32configSYSTEM
File Name: REGISTRYUSER.DEFAULT
Location: DeviceHarddiskVolume1WINDOWSsystem32configDEFAULT
File Name: REGISTRYMACHINESAM
Location: DeviceHarddiskVolume1WINDOWSsystem32configSAM
File Name: REGISTRYUSERS-1-5-20

Note that there are no file extensions on the file names.

Constants Commonly Used in WMI-based Registry Scripts

Most of the scripts in this chapter use the WMI Registry Provider, and many use constants that specify a subtree or an entry data type. These constants are expressed as hexadecimal values for subtrees or as integer values for entry data types.

Hexadecimal values for subtrees

Many of the Registry Provider methods require, as the first parameter, a hexadecimal value indicating the registry subtree that the method should act upon. Table 16.3 lists the registry subtrees and the hexadecimal values used to represent them within Registry Provider methods.

Table 16.3. Registry Subtrees and Corresponding Hexadecimal Values

Subtree

Value

HKEY_CLASSES_ROOT

&H80000000

HKEY_CURRENT_USER

&H80000001

HKEY_LOCAL_MACHINE

&H80000002

HKEY_USERS

&H80000003

HKEY_CURRENT_CONFIG

&H80000005

In your scripts, you can use either the hexadecimal values or a constant that has been set to the appropriate value. For example, you might set a constant named HKEY_USERS to &H80000003:

Const HKEY_USERS = &H80000003

In your scripts, you would then use the constant to access the subtree rather than the hexadecimal value. The constant HKEY_USERS is likely to be more meaningful for someone reading and maintaining your script than the value &H80000003 would be.

Integer values for registry entry data types

When you use Registry Provider methods that work with the data types of registry entries, you have to translate between the common string representation of the data type, such as REG_SZ, and the integers that the Registry Provider uses to refer to the data types. Table 16.4 lists the registry data types and the corresponding integers that you need within your scripts.

Table 16.4. Registry Data Types and Corresponding Values

Registry Data Type

Value

REG_SZ

1

REG_EXPAND_SZ

2

REG_BINARY

3

REG_DWORD

4

REG_MULTI_SZ

7

In other words, when you query a registry entry for its value type, WMI will return one of the integers shown in the preceding table. If you want to display the value as a string, you will have to do the conversion yourself. For example:

If intDataType = 1 Then
    strDataType = "REG_SZ"
End If

Managing the Registry

Most of the time, managing the registry involves little more than backing it up on a regular basis. Although the registry is constantly being accessed and modified, both the Windows operating system and Windows applications typically take care of these activities for you; you will rarely need to directly manipulate the contents of the registry.

However, you might need to occasionally work directly with the contents of the registry: reading, changing, creating, enumerating, and deleting entries and subkeys. This is due to the fact that the registry stores important configuration information that affects so many components of Windows itself (as well as applications and services running under Windows). For example:

  • You might read a Knowledge Base article that describes how changing a registry entry can provide a solution to a problem you have encountered.

  • You might know that a certain application you uninstalled left behind a number of registry entries, and you would like to delete those entries, and for a large number of computers.

  • You might be working with support personnel, and they ask you to find out the value of a registry entry or to determine whether or not a certain subkey exists.

  • You might have learned a great deal about how a certain component of Windows works, and you want to optimize the configuration of this component. As it turns out, you can do this only by modifying the values of its registry entries.

  • You have been informed by an application vendor that you need to change a certain registry entry to improve performance of the application on your particular system.

Do not try to memorize configuration settings stored in the registry. Instead, try to develop a sense for the types of things that you can expect to manage by modifying values in the registry. The best sources of information about registry settings are: the Resource Kit Registry Reference, MSDN® Web site, and Knowledge Base articles. Although many third-party sources provide information about the registry, do not rely on the accuracy of third-party information when it comes to the registry. If you find a registry entry referenced in a third-party source, try to verify the information provided by consulting the Resource Kit Registry Reference or another source available from Microsoft.

Caution

Caution

Changing the registry with a script can easily propagate errors. The scripting tools bypass safeguards, allowing settings that can damage your system, or even require you to reinstall Windows. Before scripting changes to the registry, test your script thoroughly and back up the registry on every computer on which you will make changes. For more information about scripting changes to the registry, see the Registry Reference on the Windows 2000 Server Resource Kit companion CD or at http://www.microsoft.com/reskit.

Backing Up the Registry

With the proper precautions, you can edit the registry without creating unrecoverable problems. Nevertheless, it is possible to make changes to the registry that will prevent Windows from loading, and force you to reinstall the operating system. However, if you are careful about making backups, a number of recovery options will be available to you should a problem arise.

Assuming you have a proven backup procedure in place, however, making registry changes is no more dangerous than installing new hardware devices. If you replace your video card and Windows will not start, you can simply remove the new video card and reinstall the old card. Likewise, if you make a change to the registry and Windows will not start, you can simply remove the new registry and reinstall the old registry.

Back up regularly

Back up your current working registry regularly. One incorrect or conflicting value can create many problems, even preventing the operating system from starting.

Saving a backup of the registry on removable media or in secure shared folders can help you restart a computer even if an error prevents you from accessing files on your hard disk.

Back up before direct editing

The Registry Provider methods bypass standard safeguards, allowing settings that can degrade performance, damage your system, or even require you to reinstall the operating system. Some settings are incompatible with others, forcing you to reload your original settings to restore system performance. Unless you have backed up the correct settings, restoring them can prove very difficult, especially if you have made other changes to the registry or if some changes are preventing you from starting Windows.

It should be noted that there is nothing inherently harmful with the Registry Provider; the caution is warranted simply because the Registry Provider requires you to know, in advance, the acceptable values for a registry entry. For example, proper computer operation could depend on a registry entry whose value is set to either 0 or 1. A command-line or graphical configuration tool would typically allow you to set this entry only to 0 or 1. The Registry Provider, by contrast, might allow you to set this to 2, a value that might create problems.

Back up before installing new hardware or software

Back up your registry before you install new hardware or software, and before you remove old hardware or software. This precaution allows you to restore the system to its previous configuration if the changes conflict or degrade performance.

You can create scripts that use the Reg.exe tool (which ships as part of the Windows 2000 Support Tools) to generate backups of the registry and to restore those backups. To make your changes effective after restoring the registry, restart your computer.

Before relying on your registry backup process, perform a practice backup and restore on a noncritical system.

Scripting Steps

Listing 16.2 contains a script backs up the registry. To carry out this task, the script performs the following steps:

  1. Use the CreateObject method to create a WshShell object and store a reference to the object in a variable.

  2. Use the Exec method of the WshShell object to invoke the Reg.exe tool to back up HKLM/System to a file named sw.hiv.

Example 16.2. Backing Up the Registry

1 Set objShell = CreateObject("WScript.Shell")
2 objShell.Exec "%comspec% /k reg.exe SAVE HKLM/System sw.hiv"

You can use the Reg.exe command-line tool itself instead of invoking it within a script. The advantage of writing a script is that you can then write a second script that uses the WshController object (see “WSH Primer”) to run the backup script on computers throughout your enterprise. If necessary, you can use the Reg.exe command-line tool to restore a saved registry hive.

Reading Entry Values and Types

The registry is filled with interesting and useful information about Windows-based computer systems, including a wealth of information about the services and applications installed on those systems.

In many cases, you can use system administration tools such as MMC plug-ins to browse registry values. These tools use registry values as the source of much of the information they provide, and thus allow you to read registry values indirectly.

There are, however, a number of useful registry values that cannot be viewed using the system administration tools included with Windows 2000. In addition, even when a tool allows you to view the registry values you are interested in, the tool might not allow you to easily view those same values across a large number of computers. For example, a security bulletin might alert you to a registry entry on servers that, if not configured properly, could leave your network vulnerable. Using a script to verify this registry value on all your servers would be much faster than attempting to verify the value one computer at a time using an application such as Regedit.

Although you can script the reading of registry values in a number of ways, a powerful approach is to use the WMI Registry Provider. The Registry Provider includes five different methods for reading registry values, with each method used to read a different data type. These five methods include:

  • GetBinaryValue

  • GetDWORDValue

  • GetExpandedStringValue

  • GetMultiStringValue

  • GetStringValue

Each of these methods will be demonstrated in this section of the chapter.

Using the Registry Provider to Read Registry Entries

The fact that there are five different methods for reading the registry might seem a bit daunting at first. Fortunately, each of these methods uses the same four parameters:

  • The subtree (such as HKEY_LOCAL_MACHINE) that contains the value being read. This must be set to one of the hexadecimal values shown in Table 16.3.

  • The path to the registry entry (for example, CurrentControlSetServices).

  • The name of the value being read. Specify an empty string (“”) to read the default value.

  • An “out” parameter, a variable that contains the value read from the registry. To display the returned value on screen, simply echo this variable.

In this chapter, variables and constants are configured for use as the method parameters. This is done to reduce the size of individual lines of code, particularly those that require long registry paths. For example, a constant for the subtree and variables for the path and value name might be configured within a script similar to this:

Const HKEY_LOCAL_MACHINE = &H80000002
strKeyPath = "SOFTWAREMicrosoftWindows Script HostSettings"
strEntryName = "TrustPolicy"

The resulting call to the GetDWORDValue method thus looks like this, with the call fitting on a single line:

objReg.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strEntryName, strValue

Without using variables and constants to represent the parameter values, this same method would look like this, requiring at least two lines of code:

objReg.GetStringValue &H8000000, _
    "SOFTWAREMicrosoftWindows Script HostSettings" , "TrustPolicy" ,strValue

Reading String-valued and DWORD-valued Entries

The majority of registry values that hold useful information for a system administrator are made up of either alphanumeric characters (REG_SZ) or numbers (REG_DWORD). String values in the registry are often clearly interpretable words, such as the name of a component manufacturer. Registry values of other types, like binary values, cannot be interpreted quite so readily.

You can read REG_SZ and REG_DWORD values by using the GetStringValue and the GetDWORDValue methods, respectively.

Scripting Steps

Listing 16.3 contains a script that retrieves both a string value and a DWORD value from the registry. To carry out this task, the script performs the following steps:

  1. Create constants that hold the hexadecimal numbers corresponding to the HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE registry subtrees.

  2. Create a variable and set it to the name of the computer where the script will run.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey in which the value is located.

  5. Create a variable and set it to the name of the entry.

  6. Use the GetDWORDValue method to retrieve the value of the entry. The value is returned in the dwValue variable that is passed to the method. GetDWORDValue is used because the data type of the value of the entry, Console, is REG_DWORD.

  7. Display the value retrieved using the Echo method.

  8. Repeat steps 4 through 7, substituting the GetStringValue method for GetDWORDValue in step 6. You must use the GetStringValue method rather than the GetDWORDValue method to retrieve the value of the second entry, TrustPolicy. This is because the data type of the value is REG_SZ (string).

Example 16.3. Reading String and DWORD Registry Values

 1 Const HKEY_CURRENT_USER = &H80000001
 2 Const HKEY_LOCAL_MACHINE = &H80000002
 3 strComputer = "."
 4
 5 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 6     strComputer & "
ootdefault:StdRegProv")
 7
 8 strKeyPath = "Console"
 9 strEntryName = "HistoryBufferSize"
10 objReg.GetDWORDValue HKEY_CURRENT_USER,strKeyPath,strEntryName,dwValue
11 Wscript.Echo "Current History Buffer Size: " & dwValue
12
13 strKeyPath = "SOFTWAREMicrosoftWindows Script HostSettings"
14 strEntryName = "TrustPolicy"
15 objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,strValue
16 Wscript.Echo "Current WSH Trust Policy Value: " & strValue

Reading a Multistring-valued Entry

A multistring value stores a list of strings. A typical use of a multistring value is demonstrated by the Autorecover MOFs entry in the HKEY_LOCAL_MACHINESOFTWARE MicrosoftWBEMCIMOM subkey. This entry holds a list of .mof files that are used to autorecover the CIM repository. The list could have been held in a series of string-valued entries, all stored under a single Autorecover MOFs subkey. However, using a multistring value is more compact and makes programmatic retrieval of the values more convenient. With a multistring entry, there is only one registry entry to read, which makes it more likely that you will retrieve every value. By contrast, storing each value in a separate registry entry requires you to individually read each of those entries. In turn, that increases the likelihood of you missing a value.

Figure 16.3 shows how a registry editor displays a multistring value. You can see that it is simply a list of strings contained under the single Autorecover MOFs entry.

Multistring Value as Displayed by a Registry Editor

Figure 16.3. Multistring Value as Displayed by a Registry Editor

You use the GetMultiStringValue method to retrieve a multistring value. The method takes as one of its parameters a variable that holds the set of strings retrieved. The strings are returned in an array, so you must use a For Each loop in your script to enumerate each of the individual strings in the array.

Scripting Steps

Listing 16.4 contains a script that retrieves a multistring value from the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey in which the value is located.

  5. Create a variable and set it to the name of the entry.

  6. Use the GetMultiStringValue method to retrieve the array of string values.

  7. For each string value in the array, echo the value to the screen.

Example 16.4. Reading a Multistring-valued Entry

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWAREMicrosoftWBEMCIMOM"
 8 strValueName = "Autorecover MOFs"
 9 objReg.GetMultiStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
10     strValueName,arrValues
11
12 For Each strValue In arrValues
13     Wscript.Echo strValue
14 Next

Reading an Expanded String-valued Entry

Registry values of the expanded string type are strings that include items that are evaluated only when the string value is actually used. For instance, a typical expanded string value is the one that holds the location of the TEMP directory:

%USERPROFILE%Local SettingsTemp

The Local SettingsTemp component of the string is treated literally, but the value of the %USERPROFILE% component can be determined only when it is actually accessed. This is because the value is dependent upon the user accessing the entry. If you look at the registry entry in Regedit.exe, you will see the value %USERPROFILE%Local SettingsTemp. However, when you retrieve the value of the entry, the value will be something like this: C:Documents and Settingsjsmith.REDMONDLocal SettingsTemp. In other words, the environment variable %USERPROFILE% is replaced with the folder (in this case, jsmith.REDMOND) that contains the user profile.

The components of expanded string types that appear between percent symbols (%) correspond to environment variables and are dependent either on the aspects of the particular user or the current configuration of the computer.

You use the GetExpandedStringValue method to retrieve expanded string values. The method takes, as one of its parameters, a variable in which the retrieved value is stored. In the retrieved value, the components of the string that appear between percent symbols are automatically evaluated. This means your script will echo a value similar to C:Documents and Settingsjsmith.REDMONDLocal SettingsTemp rather than a value like %USERPROFILE%Local SettingsTemp.

Scripting Steps

Listing 16.5 contains a script that retrieves an expanded string value from the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE registry subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey in which the value is located.

  5. Create a variable and set it to the name of the entry.

  6. Use the GetExpandedStringValue method to retrieve the value.

  7. Echo the value to the screen.

Example 16.5. Reading an Expanded String-valued Entry

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWAREMicrosoftWindows Scripting HostLocations"
 8 strEntryName = "CScript"
 9 objReg.GetExpandedStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
10     strEntryName,strValue
11
12 Wscript.Echo "The location of the cscript host is: " & strValue

Reading a Binary-valued Entry

Binary registry values are very cryptic, and difficult for humans to make sense of. However, there is useful information in the registry that is stored in binary format. As an advanced system administrator, you might find yourself interested in understanding, and possibly even editing, certain binary entries.

For example, services are organized in groups. The GroupOrderList subkey stores information about the order in which groups of services are loaded when Windows boots. This information looks similar to the following:

17 0 0 0 14 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 0 0 5 0 0 0 6 0 0 0 7 0 0 0 8 0 0 0
9 0 0 0 10 0 0 0 11 0 0 0 12 0 0 0 13 0 0 0 15 0 0 0 16 0 0 0 17 0 0 0

Tip

Tip

If you are interested in better understanding this example of binary registry values usage, consult the Registry Reference on the Windows 2000 Server Resource Kit companion CD (or on the Web at http://www.microsoft.com/reskit).

Although this type of information is rarely useful to a system administrator, it can be important to support personnel troubleshooting computer problems. If support personnel need to know the value of a binary registry entry, you can use scripts to retrieve this information.

The caution about manipulating registry entries directly is even more relevant with binary entry values. For one thing, they are cryptic, with no obvious meaning. Along the same lines, they are difficult to remember in case you need to restore their original values. Although there is no harm in reading one of these values, be very careful about modifying the value in any way.

The Registry Provider includes the GetBinaryValue method to enable you to work with binary entry values. The method takes, as one of its parameters, a variable that is used to store the retrieved value. The value is returned as an array of bytes. Therefore, to extract the value, you need to loop through the array, extracting a single byte with each pass.

Scripting Steps

Listing 16.6 contains a script that retrieves a binary value from the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE registry subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey in which the entry is located.

  5. Create a variable and set it to the name of the entry.

  6. Use the GetBinaryValue method to retrieve the value of the entry as an array of bytes.

  7. Use a For Next loop to iterate through each byte value in the array, arrValue, displaying it using the StdOut.Write method. StdOut.Write is used instead of the WScript Echo method to avoid displaying new line characters after each byte value. Using StdOut enables you to display the value on a single line, similar to this:

    17 0 0 0 14
    

    By contrast, Wscript.Echo would display each byte value on a separate line:

    17
     0
     0
     0
    14
    

Example 16.6. Reading a Binary Registry Value

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5 strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SYSTEMCurrentControlSetControlGroupOrderList"
 8 strEntryName = "Base"
 9 objReg.GetBinaryValue HKEY_LOCAL_MACHINE,strKeyPath, _
10     strEntryName,arrValue
11
12 For Each byteValue in arrValue
13    WScript.StdOut.Write byteValue & " "
14 Next

Changing String-valued and DWORD-valued Entries

Changing the values of registry entries is a common registry management task. The most challenging aspect of that task is determining which entries you need to change, and to which values they must be changed. After you have this information, you must choose the appropriate Registry Provider methods for making the change.

To change a string value (REG_SZ), you use the SetStringValue method; to change a numeric value (DWORD), you use the SetDWORDValue method. Each of these methods takes four parameters:

  • A constant that specifies the subtree in which the value being changed is located.

  • The path to the subkey in which the value is located.

  • The name of the entry with the value to be changed.

  • The new value.

These parameters are similar to the parameters used to read registry entries. The only difference is that when registry entries are read, the fourth parameter represents the value read from the registry; when registry entries are configured, the fourth parameter represents the new value being written to the registry.

Be certain to investigate whether other methods of configuration are available before deciding to script direct changes to the registry.

Caution

Caution

Regardless of where you obtain your information, always back up the registry before modifying it in any way.

Scripting Steps

Listing 16.7 contains a script that changes the values of both a DWORD and a String value in the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE registry subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey in which the entry is located.

  5. Create a variable and set it to the name of the entry.

  6. Use the SetDWORDValue method to set the value of the HistoryBufferSize registry entry to the value stored in the dwValue variable (300).

  7. Set the values of the variables holding the entry name and value to use in setting the string-valued entry.

  8. Use the SetStringValue method to set the value of the FaceName registry entry to the value (Lucida Console) stored in the strValue variable.

Example 16.7. Changing Registry String and DWORD Values

 1 Const HKEY_CURRENT_USER = &H80000001
 2 strComputer = "."
 3
 4 Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "Console"
 8 strEntryName = "HistoryBufferSize"
 9 dwValue = 300
10 objReg.SetDWORDValue HKEY_CURRENT_USER, strKeyPath, strEntryName, dwValue
11
12 strEntryName = "FaceName"
13 strValue = "Lucida Console"
14 objReg.SetStringValue HKEY_CURRENT_USER, strKeyPath, _
15     strEntryName, strValue

Creating Registry Subkeys and Entries

Managing computer system configuration by directly editing the registry usually involves changing the value of certain entries, not creating new ones. However, some registry subkeys, entries, and values can be used to affect the configuration of a computer, even though these items are not automatically created when the operating system is installed.

For example, to use the WshController object, you must first create an entry named Remote in the HKLMSOFTWAREMicrosoftWindows Script HostSettings subkey on the remote computer on which you want to run scripts. The Remote entry is not created by default, yet the WshController object cannot be used until the entry has been added and its value set to 1. This means you must create this entry and set the value before you will be able to run remote scripts either from or against a given computer.

Fortunately, you can use scripts to create both registry subkeys and registry entries.

Creating a Subkey

You rarely need to create a registry subkey. However, in some circumstances the solution to a problem — as described in a Knowledge Base article or a security bulletin — requires the addition of a subkey. If you need to create a subkey on a large number of computers, the best solution might very well be a script. After all, a single script can be used to create the subkey on every computer affected by the problem.

The Registry Provider’s CreateKey method enables you to add a new subkey. It takes two parameters: a constant indicating the subtree to which the new subkey will be added and the path of the new subkey.

Scripting Steps

Listing 16.8 contains a script that creates a subkey in the SOFTWARE key under the subtree HKEY_LOCAL_MACHINE in the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant to hold the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE registry subtree.

  2. Create a variable and set it to computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the path of the registry subkey to create.

  5. Use the CreateKey method to create the new subkey.

Example 16.8. Creating a Subkey

1 Const HKEY_LOCAL_MACHINE = &H80000002
2 strComputer = "."
3
4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
5     strComputer & "
ootdefault:StdRegProv")
6
7 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
8 objReg.CreateKey HKEY_LOCAL_MACHINE,strKeyPath

Figure 16.4 shows the newly created subkey in a registry editor.

Viewing a Newly Created Subkey Using a Registry Editor

Figure 16.4. Viewing a Newly Created Subkey Using a Registry Editor

Creating String-valued and DWORD-valued Entries

The Registry Provider’s SetStringValue and SetDWORDValue methods enable you to create string and DWORD-valued registry entries. Each of the methods accepts the same four parameters: a constant corresponding to the subtree in which the entry will be created, the path to the subkey in which the entry will be created, the name of the entry, and the value of the entry.

Note that the subkey must already exist. If the subkey does not exist, the script cannot create it for you. Because no location is available for the entry, the script will fail.

Be careful to use the method that corresponds to the data type of the value you want to create. If you want to create an entry with the DWORD value 8 and you mistakenly use the SetStringValue method and pass it the value 8, the method will interpret the 8 as the string “8” without warning you. This could incorrectly configure the registration, and lead to any number of problems..

Scripting Steps

Listing 16.9 contains a script that creates two entries in the System Admin Scripting Guide subkey, one having a string value and the other a DWORD value, in the subkey created by the script in Listing 16.8. Before running this script, run the script in Listing 16.8 to create the subkey SOFTWARESystem Admin Scripting Guide.

To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create variables and set them to the following:

    • Subkey in which the entries will be created

    • Name of the string-valued registry entry being created

    • String value of the registry entry being created

  5. Use the SetStringValue method to create the new string value.

  6. Create variables and set them to the following:

    • Name of the DWORD-valued registry entry being created

    • DWORD value of the registry entry being created

  7. Use the SetDWORDValue method to create the new DWORD value.

Example 16.9. Creating Registry String-valued and DWORD-valued Entries

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
 8
 9 strEntryName = "String Value Name"
10 strValue = "string value"
11 objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,strValue
12
13 strEntryName = "DWORD Value Name"
14 dwValue = 82
15 objReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strEntryName,dwValue

Figure 16.5 shows the newly created string and DWORD-valued entries in a registry editor.

Viewing Newly Created Entries Using a Registry Editor

Figure 16.5. Viewing Newly Created Entries Using a Registry Editor

Creating Multistring-valued Entries

Multistring-valued registry entries are relatively rare in the registry. The Registry Provider does, however, provide the SetMultiStringValue method to enable you to create these entries as needed. Because a multistring can store a list of strings, the SetMultiStringValue method accepts an array of strings as the parameter that determines the values of the entry.

Note that if you use the SetMultiStringValue method to append to an existing multistring-valued entry rather than create a new one, you have to first use the GetMultiStringValue method to retrieve the existing list of strings. This is because SetMultiStringValue overwrites any existing value. For example, suppose you have a multistring value consisting of the following strings:

A
B
C
D

If you use the SetMultiStringValue method, you cannot pass the string “E” as the sole parameter; if you do, the A, B, C, and D strings will be replaced, and the entry will contain this value:

E

To append “E” as an additional string within the value, you must pass an array containing the initial string values as well as the new value:

arrStringValues = Array("A", "B", "C", "D", "E")
objReg.SetMultiStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
    strEntryName,arrStringValues

Scripting Steps

Listing 16.10 contains a script that creates a multistring-valued entry in the registry subkey created by the script in Listing 16.8. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the subkey in which the entries will be created.

  5. Create a variable and set it to the name of the string-valued registry entry being created.

  6. Create an array variable in which to specify the multiple strings that will make up the multistring value of the registry entry being created.

  7. Use the SetMultiStringValue method to create the new multistring-valued entry.

Example 16.10. Creating Registry Multistring-valued Entries

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
 8 strEntryName = "Multi String Value Name"
 9 arrStringValues = Array("first string", "second string", _
10    "third string", "fourth string")
11
12 objReg.SetMultiStringValue HKEY_LOCAL_MACHINE,strKeyPath, _
13     strEntryName,arrStringValues

Figure 16.6 shows the newly created multistring-valued entry in a registry editor.

Newly Created Multistring-valued Entry

Figure 16.6. Newly Created Multistring-valued Entry

Creating Expanded String-valued Entries

Expanded strings are strings that can include variables; these variables are resolved when an application or a service uses the value. For example, the value of an entry that references a file might include the variable %systemroot%. When a service, such as the Event Log, references the entry, the %systemroot% variable is replaced by the name of the directory containing the Windows system files (for example, C:Windows). On a different computer, one with Windows installed on drive D, this same registry value might be replaced by D:Windows.

If you need to create an entry that includes a value that might change, such as the path environment variable or the location of the current user’s profile, you can use the SetExpandedStringValue method.

Scripting Steps

Listing 16.11 contains a script that creates an expanded string-valued registry entry in the System Admin Scripting Guide subkey created by the script in Listing 16.8. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create variables in which to specify the following:

    • Subkey in which the entries will be created.

    • Name of the expanded string-valued registry entry being created.

    • Expanded string value of the registry entry being created.

  5. Use the SetExpandedStringValue method to create the new entry with the expanded string value.

Example 16.11. Creating Expanded String-valued Entries

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
 8 strValueName = "Expanded String Value Name"
 9 strValue = "%PATHEXT%"
10
11 objReg.SetExpandedStringValue _
12     HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue

Enumerating Keys, Subkeys, and Entries

Enumeration is the process of listing the contents of a container. Just as you might open a folder and inspect its subfolders and files, you might want to inspect the child subkeys within a subkey or the entries within a subkey. For example, the script in Listing 16.1 retrieves the location of the registry hive files by listing all of the entries in the HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlhivelist subkey. The only way to determine all the registry hive files is to enumerate each entry within this subkey.

Enumeration is also used when troubleshooting configuration problems with the operating system or with an application. When a particularly stubborn problem occurs with an application, support personnel might ask you to provide a list of all the registry subkeys, entries, and values for that application. Retrieving these items programmatically is obviously much faster and easier than retrieving them using the GUI, especially if the same information must be obtained from multiple computers.

Enumerating Subkeys of a Key or Subkey

In some instances, useful configuration information is stored as the names of a set of subkeys. In the following sample script, for instance, the subkey names represent the services on a computer. In a case such as this, simply listing the names of the subkeys provides useful information.

The EnumKey method enables you to return the subkeys of a registry key or subkey. Note that the EnumKey method returns only the immediate subkeys of a key or subkey; it does not return any subkeys that might be contained within those top-level subkeys. For example, suppose you run the EnumKey method against the Control subkey shown in Figure 16.7. In this case, EnumKey will return an array consisting of the subkeys AGP, Arbiters, and BackupRestore. However, that array will not include the subkeys of those subkeys (such as AllocationOrder and DllPaths).

Sample Registry Subkeys

Figure 16.7. Sample Registry Subkeys

To return the subkeys of Arbiters and BackupRestore, you need to use a recursive function. For more information about recursive functions, see “VBScript Primer” in this book.

Scripting Steps

Listing 16.12 contains a script that enumerates the subkeys of a registry subkey. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the subkey to be enumerated.

  5. Use the EnumKey method to enumerate the subkeys, storing the results in the arrSubKeys variable.

  6. For each of the subkey names stored in the array arrSubKey, use the Echo method to display the values.

Example 16.12. Enumerating Subkeys of a Subkey

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SYSTEMCurrentControlSetServices"
 8 objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
 9
10 For Each Subkey in arrSubKeys
11     Wscript.Echo Subkey
12 Next

Enumerating Entry Names, Values, and Data Types

Registry subkeys group entries with related information, and it is often useful to display that related information. Unfortunately, this is not necessarily a straightforward procedure; after all, you cannot read a registry value unless you use the appropriate method. But how can you call the appropriate method if you do not know the data type of the value being read?

Fortunately, you can accomplish this task by using the Registry Provider EnumValues method to retrieve an array containing the entry names and an array containing the data type of each entry. After you know the entry name and its data type, you can select the appropriate method to retrieve and display the value of each entry.

Scripting Steps

Listing 16.13 contains a script that displays the name, data type, and value of all the entries within a registry subkey. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create constants that correspond to the various registry entry data types (lines 2–6).

  3. Create a variable and set it to the computer name (line 8).

  4. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  5. Create a variable and set it to the subkey to be enumerated (line 13).

  6. Use the EnumValues method to enumerate the entry names and data types, storing the results in the variables arrEntryNames and arrValueTypes.

  7. Use For Next to loop through each of the entry names stored in the arrEntryNames variable, displaying each entry name and using the corresponding data type in a Select Case statement to display a message identifying the data type (thus determining which method needs to be called to display the value of the entry). For details about each individual Get method, refer to “Reading Entry Values and Types” in this chapter.

Example 16.13. Enumerating Entries and Data Types

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 Const REG_SZ = 1
 3 Const REG_EXPAND_SZ = 2
 4 Const REG_BINARY = 3
 5 Const REG_DWORD = 4
 6 Const REG_MULTI_SZ = 7
 7
 8 strComputer = "."
 9 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
10     strComputer & "
ootdefault:StdRegProv")
11 strKeyPath = "SYSTEMCurrentControlSetControlLsa"
12 objReg.EnumValues HKEY_LOCAL_MACHINE,_
13     strKeyPath,arrEntryNames,arrValueTypes
14
15 For i=0 To UBound(arrEntryNames)
16     Wscript.Echo "Entry Name: " & arrEntryNames(i)
17     Select Case arrValueTypes(i)
18     Case REG_SZ
19         Wscript.Echo "Data Type: String"
20         objReg.GetStringValue HKEY_LOCAL_MACHINE, _
21             strKeyPath, arrEntryNames(i),strValue
22         Wscript.Echo "Value: " & strValue
23    Case REG_EXPAND_SZ
24         Wscript.Echo "Data Type: Expanded String"
25         objReg.GetExpandedStringValue HKEY_LOCAL_MACHINE _
26            strKeyPath, arrEntryNames(i),estrValue
27         Wscript.Echo "Value: " & estrValue
28    Case REG_BINARY
29         Wscript.Echo "Data Type: Binary"
30         objReg.GetBinaryValue HKEY_LOCAL_MACHINE, _
31              strKeyPath, arrEntryNames(i),arrValue
32          WScript.StdOut.Write "Value: "
33          For Each byteValue in arrValue
34              WScript.StdOut.Write byteValue & " "
35          Next
36          WScript.StdOut.Write vbCRLF
37    Case REG_DWORD
38          Wscript.Echo "Data Type: DWORD"
39          objReg.GetDWORDValue HKEY_LOCAL_MACHINE, _
40              strKeyPath, arrEntryNames(i),dwValue
41          Wscript.Echo "Value: " & dwValue
42     Case REG_MULTI_SZ
43          Wscript.Echo "Data Type: Multi String"
44          objReg.GetMultiStringValue HKEY_LOCAL_MACHINE, _
45              strKeyPath, arrEntryNames(i),arrValues
46          For Each strValue in arrValues
47              Wscript.Echo strValue
48          Next
49     End Select
50 Next

Deleting Subkeys and Entries

For the most part, you should be very careful about deleting anything from the registry. Despite that caution, however, there will likely be times when you must delete registry subkeys or entries. For example, you might discover, after adding an entry to modify the behavior of a system component, that the component is not working. Should that happen, you will likely want to revert to your previous configuration, which means removing the newly added registry entry. Another possibility is that you read a Knowledge Base article that describes a security issue whose temporary fix involves the deletion of a certain subkey.

The Registry Provider provides two methods for deleting elements of the registry: DeleteValue and DeleteKey. The DeleteValue method takes three parameters:

  • A constant representing the subtree where the entry being deleted is located.

  • The path to the subkey that contains the entry.

  • The name of the entry.

The DeleteKey method accepts two parameters: a constant representing the subtree where the subkey being deleted is located and the path of the subkey to be deleted.

Deleting Registry Entries

The DeleteValue method deletes a registry entry. (If you are wondering why the name is DeleteValue rather than DeleteEntry, it is because a number of different terms are used to refer to registry entries, including values). The script in Listing 16.14 deletes all registry entries added by the scripts in the “Creating Registry Subkeys and Entries” section of this chapter. Run those scripts before running this one — otherwise, there will be no entry for this demonstration script to delete.

Scripting Steps

Listing 16.14 contains a script that deletes entries from the registry. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the subkey from which the entries will be deleted.

  5. Create variables and set it to the names of the entries being deleted.

  6. Use the DeleteValue method to delete the various registry entries.

Example 16.14. Deleting Registry Entries

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6
 7 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
 8 strDWORDValueName = "DWORD Value Name"
 9 strExpandedStringValueName = "Expanded String Value Name"
10 strMultiStringValueName = "Multi String Value Name"
11 strStringValueName = "String Value Name"
12
13 objReg.DeleteValue HKEY_LOCAL_MACHINE,strKeyPath,strDWORDValueName
14 objReg.DeleteValue _
15    HKEY_LOCAL_MACHINE,strKeyPath,strExpandedStringValueName
16 objReg.DeleteValue HKEY_LOCAL_MACHINE,strKeyPath,strMultiStringValueName
17 objReg.DeleteValue HKEY_LOCAL_MACHINE,strKeyPath,strStringValueName

Deleting a Registry Subkey

You can use the DeleteKey method to delete a registry subkey. The script in Listing 16.15 deletes the subkey HKLMSOFTWARESystem Admin Scripting Guide, added by the script in Listing 16.8. If you have not already run Listing 16.8, you should do so before running the following script. Otherwise, there will be no subkey for this demonstration script to delete.

Scripting Steps

Listing 16.15 contains a script that deletes the HKLMSOFTWARESystem Admin Scripting Guide subkey created by the script in Listing 16.8. To carry out this task, the script must perform the following steps:

  1. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  2. Create a variable and set it to the computer name.

  3. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  4. Create a variable and set it to the subkey to be deleted.

  5. Use the DeleteKey method to delete the subkey.

Example 16.15. Deleting a Registry Key

 1 Const HKEY_LOCAL_MACHINE = &H80000002
 2 strComputer = "."
 3
 4 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
 5     strComputer & "
ootdefault:StdRegProv")
 6 strKeyPath = "SOFTWARESystem Admin Scripting Guide"
 7
 8 objReg.DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

Checking Registry Subkey Access Rights

You can use a registry editor to check and modify the access rights assigned to registry subkeys and entries. Although a registry editor allows you to connect to and manage the registry of a remote computer, it allows you to manage only one computer at a time. If you need to check the access rights of registry subkeys or entries on a large number of computers, a script that uses the Registry Provider is a far better solution.

The Registry Provider CheckAccess method allows you to determine whether the user of a script has a particular access right on a registry subkey or entry. The Registry Provider does not provide a way to list all of the access rights on a given subkeyor entry, or to make any changes to the access rights.

When you use the Registry Provider CheckAccess method to determine access rights, you must use hexadecimal values that refer to the particular rights you are interested in. Table 16.5 lists those hexadecimal values and the access rights to which they correspond.

Table 16.5. Registry Key Access Permissions and Corresponding Values

Access Right

Value

KEY_QUERY_VALUE

&H0001

KEY_SET_VALUE

&H0002

KEY_CREATE_SUB_KEY

&H0004

KEY_ENUMERATE_SUB_KEYS

&H0008

KEY_NOTIFY

&H0010

KEY_CREATE_LINK

&H0020

DELETE

&H00010000

READ_CONTROL

&H00020000

WRITE_DAC

&H00040000

WRITE_OWNER

&H00080000

The CheckAccess method will return a Boolean value: True if the user possesses the access right, False if the user does not.

Scripting Steps

Listing 16.6 contains a script that checks whether the user account under which the script is running has various access rights to a registry subkey. The script reports whether the user account has those rights on the subkey. To carry out this task, the script must perform the following steps:

  1. Create the constants that hold the hexadecimal numbers corresponding to the various access rights.

  2. Create a constant that holds the hexadecimal number corresponding to the HKEY_LOCAL_MACHINE subtree.

  3. Create a variable and set it to the computer name.

  4. Use a GetObject call to connect to the WMI namespace rootdefault, and set the impersonation level to “impersonate.”

  5. Use the Registry Provider CheckAccess method to determine whether the user account under which the script is running has the KEY_QUERY_VALUE access right on the subkey.

  6. Use the Registry Provider CheckAccess method to determine whether the user account under which the script is running has the KEY_SET_VALUE access right on the subkey.

  7. Use the Registry Provider CheckAccess method in a similar manner to check KEY_CREATE_SUBKEY and DELETE access rights.

Example 16.16. Checking Registry Key Access Rights

 1 Const KEY_QUERY_VALUE = &H0001
 2 Const KEY_SET_VALUE = &H0002
 3 Const KEY_CREATE_SUB_KEY = &H0004
 4 Const DELETE = &H00010000
 5 Const HKEY_LOCAL_MACHINE = &H80000002
 6
 7 strComputer = "."
 8
 9 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
10     strComputer & "
ootdefault:StdRegProv")
11
12 strKeyPath = "SYSTEMLastKnownGoodRecovery"
13
14 objReg.CheckAccess HKEY_LOCAL_MACHINE, strKeyPath, KEY_QUERY_VALUE, _
15     bHasAccessRight
16 If bHasAccessRight = True Then
17     Wscript.Echo "Have Query Value Access Rights on Key"
18 Else
19     Wscript.Echo "Do Not Have Query Value Access Rights on Key"
20 End If
21
22 objReg.CheckAccess HKEY_LOCAL_MACHINE, strKeyPath, KEY_SET_VALUE, _
23     bHasAccessRight
24 If bHasAccessRight = True Then
25     Wscript.Echo "Have Set Value Access Rights on Key"
26 Else
27     Wscript.Echo "Do Not Have Set Value Access Rights on Key"
28 End If
29
30 objReg.CheckAccess HKEY_LOCAL_MACHINE, strKeyPath, KEY_CREATE_SUB_KEY, _
31     bHasAccessRight
32 If bHasAccessRight = True Then
33     Wscript.Echo "Have Create SubKey Access Rights on Key"
34 Else
35     Wscript.Echo "Do Not Have Create SubKey Access Rights on Key"
36 End If
37
38 objReg.CheckAccess HKEY_LOCAL_MACHINE, strKeyPath, DELETE, bHasAccessRight
39 If bHasAccessRight = True Then
40     Wscript.Echo "Have Delete Access Rights on Key"
41 Else
42     Wscript.Echo "Do Not Have Delete Access Rights on Key"
43 End If

Monitoring the Registry

The registry contains a great deal of sensitive data, so it is worth the effort to ensure that it is secure. You secure the registry by setting appropriate access rights on the various subkeys and entries in much the same way that you secure files and folders.

You cannot, however, completely lock down the registry. After all, users and programs must be allowed access to certain areas. Because you must allow at least limited access to the registry, it is sometimes useful to be able to monitor what users are doing when they exercise this access. In certain situations, this might enable you to immediately spot potential problems.

This is especially true in light of the fact that settings in the registry can directly affect the security of your computers. WSH, for example, uses the registry entry HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows Script HostSettingsTrustPolicy in deciding whether to verify that a script is digitally signed before running it. Clearly, the value of this key needs to be secured from unauthorized modification. On certain servers, you might not want anyone, including administrators, to have the ability to run remote WSH scripts.

Because of this, you might want to periodically run a script that checks the value of the entry. If you find that the value of the entry is being changed, you can write a script that monitors the subkey and, upon detecting activity, logs information that might be useful in identifying who made the unauthorized change.

Monitoring the registry is also useful when troubleshooting computer problems. For example, a user might complain that the settings of an application are not being saved. If you know those settings are supposed to be saved in the registry, you can troubleshoot the problem by writing a script that monitors the appropriate subkey. Such a script can help you determine whether the registry is actually being changed any time the user reconfigures the application.

Monitoring Subtree-Level Events

Because subtrees receive a great deal of activity, you typically would not want to monitor an entire subtree (such as HKEY_LOCAL_MACHINE). However, this can be useful if you want to generate statistical data about registry use. For example, you might notice a large amount of disk activity when configuring an application. To help pinpoint the cause of this, you can monitor a registry subtree to see whether the disk activity is the result of a large number of changes being made to the registry.

To monitor a subtree, subscribe to the RegistryTreeChangeEvent, specifying the particular subtree you are interested in monitoring. An event will be generated only when an actual modification takes place within the subtree. No event is fired when the subtree is accessed without being modified. (For example, you will not be notified anytime an application reads a registry entry.) The event does not include information about the change that took place; it simply provides notification that a change has occurred. You cannot use the event to determine who made the change or what change was made.

In scripts that monitor the registry, you will typically use the GetObjectText_ method to echo the fact that a change has been made. This is the only information about the change that is available to you. The output from the scripts used in this section of the chapter will look similar to this:

Received Registry Change Event
------------------------------

instance of RegistryTreeChangeEvent
{
        Hive = "HKEY_LOCAL_MACHINE";
        RootPath = "";
        TIME_CREATED = "126746045405872087";
};

The script in Listing 16.17 subscribes to the RegistryTreeChangeEvent for the HKEY_USERS subtree. You can modify the script to monitor a different subtree by changing HKEY_USERS to HKEY_LOCAL_MACHINE or any other registry subtree.

Scripting Steps

The script in Listing 16.17 monitors and reports on events in the HKEY_USERS subtree, displaying messages regarding each detected event. To carry out this task, the script must perform the following steps:

  1. Use the GetObject method to connect to the WMI service.

  2. Use the CreateObject method to create an event sink.

  3. Use ExecNotificationQuery to register for the event.

  4. Put the script in sleep mode while waiting on the event.

  5. Implement the event handler as a subroutine that uses the Echo method to display a message indicating that a registry change event was received.

Example 16.17. Monitoring Events at the Subtree Level

1 strComputer = "."
2 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
3     strComputer & "
ootdefault")
4
5 Set wmiSink = WScript.CreateObject("WbemScripting.SWbemSink", "SINK_")
6
7 wmiServices.ExecNotificationQueryAsync wmiSink, _
8     "SELECT * FROM RegistryTreeChangeEvent WHERE Hive='HKEY_USERS'" _
9         & " AND RootPath=''"
10
11 Wscript.Echo "Listening for Registry Change Events ..." & vbCrLf
12
13 Do While(1)
14     Wscript.Sleep 1000
15 Loop
16
17 Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext)
18     Wscript.Echo "Received Registry Change Event" & vbCrLf & _
19         "------------------------------" & vbCrLf & _
20             wmiObject.GetObjectText_()
21 End Sub

Monitoring Subkey-Level Events

You might want to monitor an entire subkey if you are interested in changes happening to a group of related registry entries. For instance, if you are troubleshooting an application that does not seem to save user customization data and you know the data should be stored in the registry, you can monitor the registry subkey of the program where the configuration settings are stored, in an effort to understand what is going wrong.

To monitor a subkey, subscribe to the RegistryKeyChangeEvent, specifying the subtree where the subkey you are interested in monitoring is located as well as the path of the subkey you want to monitor. Like the RegistryTreeChangeEvent, the RegistryKeyChangeEvent is fired when a modification is made to the subkey being monitored and the event does not provide any information beyond the fact that a modification has taken place.

Scripting Steps

The script in Listing 16.18 monitors and reports on events in the subkey. To carry out this task, the script must perform the following steps:

  1. Use the GetObject method to connect to the WMI service.

  2. Use the CreateObject method to create an event sink.

  3. Use ExecNotificationQuery to register for the event.

  4. Put the script in sleep mode while waiting on the event.

  5. Implement the event handler as a subroutine that uses the Echo method to display a message indicating that a registry change event was received.

Example 16.18. Monitoring Events at the Subkey Level

1 strComputer = "."
2 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
3     strComputer & "
ootdefault")
4
5 Set wmiSink = WScript.CreateObject("WbemScripting.SWbemSink", "SINK_")
6
7 wmiServices.ExecNotificationQueryAsync wmiSink, _
8     "SELECT * FROM RegistryKeyChangeEvent WHERE Hive= " _
9         & "'HKEY_LOCAL_MACHINE' AND " _
10               & "KeyPath='SOFTWARE\Microsoft\Windows NT\CurrentVersion'"
11
12 Wscript.Echo "Listening for Registry Change Events ..." & vbCrLf
13
14 Do While(1)
15     Wscript.Sleep 1000
16 Loop
17
18 Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext)
19     Wscript.Echo "Received Registry Change Event" & vbCrLf & _
20         "------------------------------" & vbCrLf & _
21             wmiObject.GetObjectText_()
22 End Sub

Monitoring Entry-Level Events

There are likely to be times when you want to monitor changes to specific registry entries. For example, certain registry entries are used to configure system security and are therefore potential targets for anyone trying to compromise the computer. You can create a script to monitor these entries to be sure that they are not being altered.

To monitor an entry, subscribe to the RegistryValueChangeEvent class, specifying the subtree, the subkey, and the name of the entry to be monitored. As with the other registry change events, the RegistryValueChangeEvent is fired when a modification is made to the entry being monitored, and the event does not provide any information beyond the fact that a modification has taken place.

Scripting Steps

Listing 16.19 contains a script that monitors events at the registry entry level. To carry out this task, the script must perform the following steps:

  1. Use the GetObject method to connect to the WMI service.

  2. Use the CreateObject method to create an event sink.

  3. Use ExecNotificationQuery to register for the event.

  4. Put the script in sleep mode while waiting on the event.

  5. Implement the event handler as a subroutine that uses the Echo method to display a message indicating that a registry change event was received.

Example 16.19. Monitoring Events at the Registry Entry Level

1 strComputer = "."
2 Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & _
3     strComputer & "
ootdefault")
4
5 Set wmiSink = WScript.CreateObject("WbemScripting.SWbemSink", "SINK_")
6
7 wmiServices.ExecNotificationQueryAsync wmiSink, _
8     "SELECT * FROM RegistryValueChangeEvent WHERE Hive= " _
9         & "'HKEY_LOCAL_MACHINE' AND KeyPath= " _
10           & "'SOFTWARE\Microsoft\Windows NT\RegisteredOwner' AND " _
11                & "ValueName='CSDVersion'"
12
13 Wscript.Echo "Listening for Registry Change Events ..." & vbCrLf
14
15 Do While(1)
16     WScript.Sleep 1000
17 Loop
18
19 Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext)
20     Wscript.Echo "Received Registry Change Event" & vbCrLf & _
21         "------------------------------" & vbCrLf & _
22             wmiObject.GetObjectText_()
23 End Sub
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset