Do you have a scripting-related question or problem? You can send your question or problem to [email protected].
I'm trying to automate modifying and deleting several Registry keys on about 50 networked Windows NT 4.0 workstations. I'm using Windows Script Host (WSH) to make the modifications because the .reg file approach doesn't handle deletions. The script is simple, as Listing 1 shows. When I run this script, I receive an error message that says the HKEY_LOCAL_MACHINE\SOFTWARE\ODBC(check)\odbc.ini key can't be deleted. The odbc.ini key exists, and I'm logged on as the administrator on the local workstation, so what's wrong?
The problem you're encountering is a WSH limitation. In the script, you use the WSH Shell object's RegDelete method to delete the specified Registry key (i.e., the target key). This target key, however, has subkeys. RegDelete can't delete target keys that contain subkeys. Values under the target key aren't a problem because the values are removed as part of the delete key operation. However, you need to recursively enumerate and delete all the subkeys under the target key before you can delete the target key. WSH doesn't provide a built-in means to enumerate subkeys under a target key, so you must take another route. Here are some options:
- You can use a command-line utility, such as the Microsoft Windows NT Server 4.0 Resource Kit's reg.exe utility. If you don't have the resource kit, you can download reg.exe from Microsoft's FTP site at ftp://ftp.microsoft.com/bussys/winnt/winnt-public/reskit/nt40/i386/reg_x86.exe.
- You can use hard-coded subkey names in your script to delete all the subkeys under the target key. This option is viable only if you're certain that all the target machines' Registries are identical.
- You can develop a script that first recursively deletes all the subkeys beneath the target key, then deletes the target key. You can use either Perl in conjunction with the Win32::Registry module or WSH in conjunction with Windows Management Instrumentation (WMI). Here's a detailed look at each approach:
Perl and Win32::Registry. Perl's Win32::Registry module lets you walk through and delete an entire Registry branch. The script RegDelKey.pl shows how to use this module. You can find the script in the Code Library on the Win32 Scripting Journal Web site at http://www.win32scripting.com. The script includes comments to help you understand the code.
Listing 2 contains the most important part of RegDelKey.pl—the DeleteSubkeys subroutine. This recursive subroutine deletes all the subkeys under the target key, which $strKeyToDelete identifies. DeleteSubkeys uses the Win32::Registry GetKeys method to enumerate and traverse the branch under the target key. Without GetKeys, you'd encounter the same problem you did with the WSH Shell object's RegDelete method. As DeleteSubkeys traverses the target Registry path, the Win32::Registry DeleteKey method deletes the subkeys returned by GetKeys, which has the side effect of deleting all values contained in the subkey.
After the subroutine deletes all the subkeys, it returns control to the main body of the script. This code, in turn, deletes the now empty target key and closes the Registry hive.
To use RegDelKey.pl, you need to download and install ActivePerl, which is available from ActiveState at http://www.activestate.com/activeperl/download.htm. You also need to change the value of the $strComputer scalar. This scalar can be the local machine name or a remote computer name.
To run the script, type the script's name at a command prompt with the code
C:\scripts> perl regdelkey.pl
WSH and WMI. You can use WSH with the WMI Registry Provider StdRegProv. This provider offers more than 15 methods, which you call from Windows Script (WS), to manipulate the Registry. These methods include EnumKey (enumerates the subkeys under a Registry key) and DeleteKey (deletes subkeys).
The script RegDelKey.vbs shows how to use StdRegProv. (You can find the script, complete with comments, in the Code Library on the Win32 Scripting Journal Web site.) Like the DeleteSubkeys subroutine in RegDelKey.pl, the subroutine KillKey is the most important part of RegDelKey.vbs. This recursive subroutine, which Listing 3 contains, deletes all the subkeys under the target key. KillKey accomplishes this task by first using StdRegProv's EnumKey method to enumerate the branch under the target key. Then, as KillKey traverses the target Registry path, KillKey uses StdRegProv's DeleteKey method to delete the subkeys returned by EnumKey. DeleteKey also deletes all values contained in the subkeys. Unlike the DeleteSubkeys subroutine in RegDelKey.pl, KillKey deletes the target key rather than letting the main body of the script perform this task.
To use RegDelKey.vbs, you need to install WMI on the machine on which you'll run the script and on the target machine. You can use WMI on machines running Windows 2000 (Win2K) or NT 4.0 with Service Pack 4 (SP4) or later. You can download the WMI 1.5 Core Software Installation from the Microsoft Developer Network (MSDN) at http://msdn.microsoft.com/downloads/sdks/wmi/download.asp. Before you use RegDelKey.vbs, you need to modify strComputer so that it points to a WMI-enabled target machine in your network. If you want to delete a different Registry path, you also need to modify strKeyToDelete. To run RegDelKey.vbs, type the following code at the command prompt:
C:\scripts> cscript regdelkey.vbs
Choosing which scripting solution is right for you depends on two factors. First, you need to consider the scripting languages with which you're familiar. This real-world example demonstrates why knowing more than one scripting language is advantageous. Second, you need to consider your infrastructure. To use the Perl/Win32::Registry solution, you need to install ActivePerl on only one workstation. From that workstation, you can point the script to any remote client in the trusted network. To use the WSH/WMI solution, you need to install WMI on two machines. If you're using Win2K, the dual installation isn't a problem because WMI is the core set of management interfaces built into the OS.