Use a script to remotely update multiple machines’ registries
The ability to remotely perform registry updates on multiple computers is useful in all sorts of situations. When something in the registry configuration compromises security, quickly performing registry updates is an important security measure. Remotely updating multiple computers' registries is also helpful when you need to apply a custom OS change to a set of systems or apply an additional registry entry so that software operates properly. Whatever the reason, performing registry updates centrally is crucial in midsized to large networks.
The Microsoft Resource Kit Group recently asked me to write a series of scripts for the "Best Practice Guide for Securing Active Directory Installations and Day-to-Day Operations: Part II," which you can download from http://www.microsoft.com/downloads/details.aspx?familyid=c0dbeb7e-d476-4498-9f6c-24974fb81f1e&displaylang=en. One of the scripts that I wrote, ApplyReg.vbs, remotely updates the registries of multiple computers. Although you can use the Reg utility with the Add parameter to perform remote registry updates, Reg works for only a limited set of registry keys. In contrast, ApplyReg.vbs doesn't impose any key limits. The script performs registry updates against a list of computers that you provide, then it creates a report that notes whether each computer's set of registry updates was successful.
ApplyReg.vbs relies on several technologies: Active Directory (AD), Active Directory Service Interfaces (ADSI), Windows Management Instrumentation (WMI), Windows Script Host (WSH) 5.6, and VBScript. (If you want to use a Perl script to apply registry updates, see "Checking Remote Registries," May 2002, http://www.winnetmag.com, InstantDoc ID 24540, for information about using Perl to work with the registry.) Let's look at how to prepare for ApplyReg.vbs (including how to test the script), how to run the script in production, and how the script works.
Preparing to Use the Script
Microsoft's registry mantra goes something like this: "Do not edit the registry unless you have no alternative. The registry editor bypasses standard safeguards, allowing settings that can damage your system or even require you to reinstall Windows. If you must edit the registry, back it up first." If you didn't recognize the importance of this message before, believe it now. ApplyReg.vbs is capable of editing—and damaging—the registry on thousands of computers in minutes.
In keeping with Microsoft's registry warning, before you use ApplyReg.vbs in a production network, you need to test and retest the script in a lab. The test systems should accurately represent the production computers targeted for the registry update.
ApplyReg.vbs relies on AD to determine the host name or NetBIOS name of the computers in which it will apply the registry update. Therefore, make sure that all test computers, including the computer that will run ApplyReg.vbs, are members of an AD domain. After you configure the test systems, you need to either download or create several files:
- You need to download ApplyReg.vbs from the Windows & .NET Magazine Web site at http://www.winnetmag.com. (Enter 40714 in the InstantDoc ID text box, click the Download the Code link, and download the 40714.zip file.)
- You need to create a registry (.reg) file that contains the registry updates you want to apply. I've included a sample registry file named AAA123Test!!!.reg, which is in the 40714.zip file. You can use this sample file to take ApplyReg.vbs for a test run. This registry file, however, is only a sample file. Don't apply it to computers in a production network. If you're unfamiliar with the format of a registry file, see the sidebar "The Registry File Format" and review the contents of AAA123Test!!!.reg.
- You need to create a text (.txt) file that contains a list of computers to update. In this input file, list the target computers by their distinguished names (DNs). Place each DN on a separate line, enclose each DN in quotation marks, and append a comma after the ending quotation mark. Do not include blank lines. At the top of the input file, enter a column heading, such as Distinguished Name. Figure 1 shows an example of a valid list. Adding the column heading and adding the trailing commas are important; otherwise, ApplyReg.vbs might not work correctly.
An alternative to manually creating the input file is to use the script ComputerSearch.vbs to programmatically generate a valid list for ApplyReg.vbs to read. The "Best Practice Guide for Securing Active Directory Installations and Day-to-Day Operations: Part II" download includes ComputerSearch.vbs. The guide's "Identifying Computers to Receive New Registry Settings with ComputerSearch.vbs" section describes how to create and run ComputerSearch.vbs. ComputerSearch.vbs will generate a properly formatted input file that contains the DNs of the computers in your domain.
Place ApplyReg.vbs, your registry file, and your input file on the computer from which you'll run ApplyReg.vbs (which I call the source computer). Make sure that the source computer has WSH 5.6 installed. ApplyReg requires WSH 5.6 because it relies on the WshNamed object and the WScript object's StdOut property. These two features aren't available in earlier versions of WSH. You can download WSH 5.6 for Windows 2000, Windows NT 4.0, Windows Me, and Windows 98 from http://msdn.microsoft.com/library/default.asp?url=/downloads/list/webdev.asp. Windows Server 2003 and Windows XP already include WSH 5.6. However, Microsoft released a build update for WSH 5.6 in XP. You might want to download and install that update if you haven't done so already.
The source computer and all the target computers require WMI. The source computer requires WMI to make a remote connection to each target computer's WMI repository. Each target computer needs WMI's Registry Provider (StdRegProv) to make the registry updates. All computers running WMI have StdRegProv in the root\default namespace.
Except for NT 4.0 and Win98, all Windows OSs include WMI. You can download WMI CORE 1.5 for Win98 from http://msdn.microsoft.com/library/default.asp?url=/downloads/list/wmi.asp. The WMI CORE 1.5 download for NT 4.0 isn't available on the Microsoft site, so I've included it in the 40714.zip file.
Testing the Script in the Lab
After you have your lab set up, you can test ApplyReg.vbs. As an example, let's apply a registry file named update.reg to update the registry of the target computers listed in the input file named computers.txt. After you create update.reg and computers.txt following the instructions I gave previously, copy ApplyReg.vbs, update.reg, and computers.txt to a directory. Open a command-shell window, change from the current directory to the directory that contains the three files, and type
cscript applyreg.vbs /r:update.reg /f:computers.txt
(Although this command appears on two lines here, you would enter it all on one line when you type it on the command line.) Press Enter. ApplyReg.vbs applies the changes specified in update.reg to all the machines in computers.txt and provides a report that states whether the update was successful. The report's unique filename appears after the script has finished creating it. After the test run, make absolutely sure that the update didn't damage the registry or interrupt any target computer's normal operation.
Next, on a test computer not listed in computers.txt, apply update.reg manually. One way to do this is to navigate in Windows Explorer to the folder that contains update.reg and double-click the file. Compare the manual registry modifications with the registry modifications that ApplyReg.vbs automatically deploys.
Running the Script in Production
If ApplyReg.vbs is successful in the lab, you can begin deploying the update in your production network. I suggest that you start small by updating just a handful of target computers in your production network. Verify that all the target production computers function properly after the update. If all the target computers check out, you can slowly increase the number of target computers. Check the report after each script run. The report will inform you whether a computer was unreachable, whether the input list had an incorrect DN, or whether another error prevented access to the remote registry. You can use the report's information to determine which computers require additional runs of ApplyReg.vbs. If you can't access a remote registry because of a permission problem, verify that you have administrator or equivalent permissions on the remote computer. By default, you must have administrator rights to perform remote registry updates. For more information about remote registry permissions, see the Microsoft article "How to Restrict Access to the Registry from a Remote Computer" (http://support.microsoft.com/?kbid=153183).
Understanding How the Script Works
As I mentioned previously, ApplyReg.vbs relies on several technologies to do its work. WSH 5.6 provides the engine that processes the script's code and provides some key objects, such as the WshArguments object, which passes the command-line parameters to the script, and the Regular Expression (RegExp) object, which evaluates registry strings. ADSI lets the script connect (i.e., bind) to AD and read each computer object's attributes. WMI lets the script bind to a remote registry and use StdRegProv to update the registry.
ApplyReg.vbs begins by defining several constants and global variables, then calls the CheckForCScript subroutine, which Web Listing 1 shows (http://www.winnetmag.com, InstantDoc ID 40714). This subroutine verifies that you're running the script with the CScript host. You must use CScript because WScript doesn't support the WScript object's StdOut property.
After verifying the host, the script sets the input file you specified with the /f parameter and the registry file you specified with the /r parameter to the strRptFileName and strRegFileName variables, respectively, as Web Listing 2 shows. (If you don't specify the /f and /r parameters when you launch ApplyReg.vbs, the script displays a message informing you that both parameters are necessary.) The script calls the SampleCommandLine function to display the command-line syntax, then terminates.
Next, ApplyReg.vbs uses the Script Runtime Library's Dictionary object to define the five registry root keys (e.g., HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT) as constants. The script later uses these constants to access the registry keys and subkeys that the registry file specifies. Using the Dictionary object is a straightforward scripting operation, so I haven't included a listing for it. If you're unfamiliar with the Dictionary Object, see the Microsoft Developer Network (MSDN) documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/jsobjdictionary.asp.
ApplyReg.vbs creates a comma-separated value (CSV) report that you can view after the script runs. To uniquely name this report, the script uses the GenFileName function, which takes a filename (without the extension) as an input parameter (i.e., the prefix parameter). In this case, the prefix parameter is ApplyReg, as Web Listing 3 shows. GenFileName creates a unique filename by appending the date and time to the filename ApplyReg. For example, if you ran ApplyReg.vbs on April 16, 2003, at 11:43 a.m. and 53 seconds, GenFileName would generate a file named ApplyReg-030416-114353.csv. Note that the date follows the YYMMDD format. Callout A in Web Listing 3 shows the GenFileName function call. The rest of the code is the function itself.
Given the report name, ApplyReg.vbs creates an instance of the Script Runtime Library's FileSystemObject object, which the script uses to create, open, and write to the report. The script also uses this object to open the registry file for reading, as the code in Web Listing 4 shows.
ApplyReg.vbs creates a RegExp object to evaluate each line of the registry file. This evaluation lets the script determine whether it should create a registry key or a registry entry. A registry entry is a value name, a data type, and a value. If the script needs to create a registry entry, RegExp also determines the type of entry to make: String, Binary, DWORD, Expandable String, or Multi-String. The code in Web Listing 5 demonstrates how the script creates the RegExp object and sets that object's properties.
Before the registry file evaluation begins, ApplyReg.vbs calls the BindDN function to attempt an ADSI bind operation for each DN in the input file. BindDN takes as input one line from the input file at a time and returns a string of values, depending on the success or failure of various operations within the function, as Figure 2 shows.
Listing 1 shows the BindDN function. Notice how the function sets the BindDN output values that appear in Figure 2. In the case of BindDN = strDN||None||Invalid, which callout A in Listing 1 shows, the function doesn't find the DN in AD. Either the specified DN is invalid or the computer name has been deleted from AD. In the case of BindDN = strDN||strComptName||Host, which callout B in Listing 1 shows, the function finds the DN and sets the strComptName variable to the dNSHostName attribute (i.e., the computer's DNS host name). In the case of BindDN = strDN||strComptName||NetBIOS, which callout C in Listing 1 shows, the function finds the DN but doesn't set the dNSHostName attribute for the computer. Therefore, BindDN retrieves the cn attribute, which is mandatory for computer objects. The cn attribute is usually the computer's NetBIOS name.
Next, VBScript's Split function teases apart the BindDN function's output by using two pipe symbols (||) as a delimiter. The Split function assigns the resulting three pieces of information to the arrComputerInfo array, as callout A in Web Listing 6 shows. The script uses this array for code evaluation and for writing information to the report. The first item in the array, arrComputerInfo(0), contains the computer's DN, which the script assigns to the strDN variable. The second item in the array, arrComputerInfo(1), contains the computer name, which the script assigns to the strComputerName variable. The value is None, the host name, or the NetBIOS name. The third item in the array, arrComputerInfo(2), contains general information, which the script assigns to the strNote variable. This value is Invalid, Host, or NetBIOS.
Why bother going to the trouble of attempting a binding operation and retrieving AD attributes? Because before updating a computer's registry, the script must make sure it can find the target computer. If the computer exists in AD and BindDN returns a dNSHostName or cn attribute, ApplyReg.vbs attempts to ping the computer on the network by using the computer's DNS name or NetBIOS name. To accomplish this task, the script loads the WshShell object and uses this object to call the Ping utility, as Web Listing 7 shows. This procedure is a good way to find computers that are online. For more information about why this procedure is a good choice for finding computers that are online, see "Remote Administration with WMI," February 2003, http://www.winscriptingsolutions.com, InstantDoc ID 37596. Another good resource is "Tales from the Script - November 2002" (http://www.microsoft.com/technet/treeview/default.asp?url=/technet/columns/scripts/sg1102.asp?frame=true).
When the ping succeeds, the script attempts to connect to StdRegProv, as callout A in Web Listing 7 shows. When the connection attempt succeeds, ApplyReg.vbs performs the registry update. To perform the update, the script reads each line of the registry file and sets the strLine variable equal to the line's value. Then RegExp evaluates the pattern in strLine. When the pattern matches a key value, WMI's CreateKey method creates the key, as the code in Listing 2 shows. If no match occurs for a key pattern, the script tests each possible value name that's allowed in the registry. When a pattern match occurs, ApplyReg.vbs calls the appropriate routine. The code in Listing 3 shows the pattern matches that the script attempts for each type of entry and the name of the subroutine that the script calls when a pattern match occurs. If you're unfamiliar with regular expressions and would like a primer, see Stephen Ramsay's excellent article, "Using Regular Expressions" (http://etext.lib.virginia.edu/helpsheets/regex.html).
After the script reads all the lines of the registry file, the script sets the strStatus variable to Registry update applied. If the host is unreachable because the ping operation didn't return a reply, the script sets strStatus to Host unreachable and strNotes to Verify that this host is online. Then, the FileSystemObject's WriteLine method writes the values contained in strDN, strComputer, strStatus, and strNotes to the report file. After the script processes all the lines in the input file, you'll see a console message that states the report data has been saved.
It's Time to Save Time
Preparing to use ApplyReg.vbs involves downloading the script, creating a registry file, building a list of computer names, and thoroughly testing the script in the lab. If everything checks out, you're ready to use ApplyReg in a production network. Make updates on a small subset of your production computers until you're satisfied that the registry update is working properly. If everything checks out, your careful testing and cautious deployment will save you countless hours of performing manual registry updates.