You probably use Control Panel or other tools for most server-tuning tasks, but some recommended fixes require you to edit the registry by hand. Manually editing the registry can easily mess up your OS to the point of no return, so if a registry modification is important enough to make by hand, it's important enough to make consistently on all applicable computers. You probably also want to document the registry edit and its purpose, as well as confirm the changes.
If you've ever manually edited the registry on more than a few computers, you probably know one way to make changes without navigating through the HKEY maze more than once. You can save the edited key as a .reg file, then import that file to all the computers that need the same fix. However, that approach doesn't log the change and supports only a limited amount of granularity (you can import a key, but you can't import one edited value). A better approach is to use VBScript to write your change to the registry and record changes in the computer's Application log so that you—and others—can tell what edits you've made and why. You can modify the same script to read the registry and thus confirm your changes.
A Good Example
You can edit any part of the registry through VBScript, but for an example, let's suppose that you're editing the registry on your application servers so that a particular application will refer to usernames instead of computer names. The edit is application-specific, so you must be sure to edit the correct application's subkey. The subkey's final edited value is the sum of two hexadecimal numbers (rather than something easy, such as 0 or 1), so you must be sure to enter the right number on all application servers. The edit's purpose isn't obvious, so you'll want a record explaining the edit.
To accomplish these goals, you need a script that performs several tasks. The script must create a WshShell object (which represents the Windows Shell and thus gives you programmatic access to the registry-editing tools and Event Viewer), write the change to the registry, and record the change in the Application log.
Writing the Change
I discuss WshNetwork, a Windows Script Host (WSH) 2.0 object representing network-accessible printers and drives, in "Connecting to Printers," August 2002, http://www.winnetmag.com, InstantDoc ID 25652, and "Connecting Users to Network Resources," June 2002, http://www.winnetmag.com, InstantDoc ID 24893. WshShell, another WSH object, deals with certain Windows Shellrelated objects, including the registry editor and Event Viewer.
WshShell supports several methods for reading or editing the registry. Generally, using the registry-editing methods is simple as long as you're exact; putting even an extra space in the string will return an error. For this example, you're going to work with the RegRead method, which reads a subkey or value, and the RegWrite method, which writes a subkey or value. These methods use a simple syntax:
WshShell.RegWrite strName, varValue, \[strtype\]
The RegRead method reads the key or value that you specify with the strName argument. Each method accesses registry keys according to the keys' full pathname, so you must use the familiar predefined key names as part of the strName argument:
- HKEY_CURRENT_USER (or HKCU)
- HKEY_CLASSES_ROOT (or HKCR)
- HKEY_LOCAL_MACHINE (or HKLM)
The RegWrite method writes to the registry the subkey or value that you specify with the varValue argument. If strName ends with a backslash (\), RegWrite writes varValue to the registry as a subkey. Otherwise, RegWrite writes varValue to the registry as a value. You can use the optional strtype argument to define the value's type: REG_SZ or REG_EXPAND_SZ writes string values, REG_DWORD writes a 32-bit integer value, and REG_BINARY writes a 32-bit binary value.
Now that you have a basic understanding of the tools, you can build a registry-editing script, which Listing 1 shows. To customize this script for your environment, simply substitute the appropriate subkey and value.
Recording and Confirming the Change
The script that Listing 1 shows makes an edit, but with this script, the only ways to prove that you made a change are to run the application (to show the expected behavior) or to browse through the registry. If neither approach appeals to you, you can add some code to the script to record and describe the change in the Application log.
To record a change in this manner, employ the RegRead method with another method: LogEvent. LogEvent is almost as simple as RegRead but takes as arguments both a string—which you can use to explain the change—and a code that identifies the type of event that took place. These types, which Table 1 lists, are familiar to anyone who uses the Event Viewer. LogEvent uses the following syntax:
WshShell.LogEvent eventcode, strmessage \[strtarget\]
The eventcode argument specifies the type of event to record, the strmessage argument specifies the message that appears in the Application log, and the optional strtarget argument supplies the name of the computer on which to record the changes. (You can keep a centralized record—in which case you can use WshNetwork's ComputerName property to identify the computer for which you made the change—or you can maintain the record on the local server.) The final version of the script, which Listing 2 shows, is similar to the script that Listing 1 shows but includes a new variable and the LogEvent method.
Sometimes you need to confirm and record, rather than change, a server's registry settings. For example, suppose someone edits a server's registry to change the port on which Windows 2000 Server Terminal Services listens (port 3389 by default). Anyone who attempts to connect to that server without specifying the new port will receive a vague and unhelpful error message stating only that the client couldn't connect to the terminal server. To troubleshoot this problem, you can use a short script, such as the one that Listing 3 shows, to read the registry and determine on which port Terminal Services is listening. This script uses WshShell's RegRead method (instead of RegWrite) to get the current value of HKEY_LOCAL_MACHINE\CurrentControlSet\Control\Terminal Server\WinStations\RDP-TCP\PortNumber, assign the value to a variable, then write that value to the Application log with explanatory text.
Quick, Simple, and Consistent
Any time you need to make the same registry edit to many servers (and record the change) or want to determine current registry settings without going hunting, the WshShell RegRead, RegWrite, and LogEvent methods can save you a lot of time and trouble. And you can probably think of several other VBScript capabilities that might enhance these registry-editing tools. How about using the InputBox function (which I describe in "Connecting to Printers") to prompt the person running the script for a specific value? Or why not use Select Case (which I also describe in "Connecting to Printers") so that one script can apply different registry edits to different groups of servers? These useful tools offer multiple options.