Use a menu-driven script to store and apply registry modifications
I often use Group Policy to customize PC and server settings. However, sometimes I need more control, so I manually make registry changes. The problem with the manual approach is that between new installations, I often forget how to accomplish the registry changes.
Like most administrators, I'm cautious about making registry changes, so I decided to come up with a way to store registry-modification information and perform the modifications with minimal risk. My first crude solution was to maintain a folder in which I kept a number of common .reg files. Whenever I made a new registry change that I thought I might need later, I added a new .reg file to the folder. In many cases, the .reg files came in pairs, with one file to enable a setting and another file to disable the same setting. With so many files, I had a hard time keeping them organized, which made finding a particular .reg file difficult.
After examining my usage patterns with the .reg files, I discovered there were only about 20 or 30 files that I used regularly. I realized that the optimal solution would be to integrate the information in those files into a menu-driven script. That way, I could easily find and select the registry modification I needed. And by putting that menu-driven script on a shared folder and connecting to that share, I could make the changes to whatever computer I was logged on to.
Figure 1 shows the menu interface of my menu-driven script, RegMods.Menu.bat. Listing 1 shows an excerpt from this script. You can download the entire script from the Windows Scripting Solutions Web site. (Go to http://www.windowsitpro.com/windowsscripting, enter 49360 in the InstantDoc ID text box, then click the 49360.zip hotlink.)
RegModsMenu.bat uses Choice .exe with the If ERRORLEVEL command to route the script's flow to the code that will perform the registry modification selected from the menu. The script uses the Reg.exe tool to perform that modification.
The Command of Choice
Choice.exe has been around since the early days of DOS. The Choice command lets you use keyboard selections to route a script's flow to the appropriate section of code. In the original RegModsMenu.bat script, I used Choice.exe from the Microsoft Windows 2000 Server Resource Kit. This version of the tool worked great until I tried to run the script on a Windows Server 2003 machine. The syntax for the version of Choice.exe in the Win2K resource kit differs slightly from the syntax for the version of Choice.exe built into Windows 2003.
Scripts can fail if different versions of the same tool use different syntaxes. There are several ways to resolve a syntax problem. One way is to select a version of the tool that works correctly on all the OSs you're working with, then place this version in a shared folder and use that copy each time you use the tool. That way, you can get consistent results without worrying about what version is on the local machine. RegModsMenu.bat includes code to specify a remote location for Choice.exe and Reg.exe, as callout A in Listing 1 shows. This code is commented out but can easily be implemented by removing the double colons and specifying a remote path.
Another way to resolve a syntax problem is to have your script detect what version of the tool exists on a machine, then have separate sections of code for each version of the tool. This technique works well if you know a tool exists on all the machines but the versions might differ. I used this technique in RegModsMenu.bat.
The first step in using the version-detection technique is to determine one easily detectable difference between the versions' syntaxes. For example, the version of Choice.exe in Windows 2003 includes an /M switch but the version in the Win2K resource kit doesn't.
The next step is to write code that looks for and reacts to this difference. For example, as callout C in Listing 1 shows, RegModsMenu.bat runs the Choice /? command and determines whether the /M switch is present in the command's output.When this switch is present, the script jumps to the code that uses this switch, as callout D shows. When the /M switch isn't present, the script goes to the code that doesn't use this switch, as callout E shows.
The version-detection technique is well suited for those situations in which there isn't a single version of the tool that works on all the target computers. Version detection also works well when a command is used only a few times. However, when you have a script that uses a command many times, the technique might be impractical. For example, RegModsMenu.bat uses Choice.exe only once, so including two versions of the Choice command doesn't add much code to the script. However, the script uses Reg.exe 26 times. For illustration purposes, let's say that different versions of Reg.exe have different syntaxes. (Fortunately, in reality, this isn't true.) Having to include two versions of the Reg command for each of those 26 instances would add a lot of code, making the remote-path approach a better solution.
As I mentioned previously, Choice .exe lets you use keyboard selections to route a script's flow. Choice.exe assigns values to the keys you specify. The first key you specify is assigned the value of 1, the second key you specify is assigned the value of 2, and so on. Thus, in this case, when the user presses the A key on the keyboard to select the My Computer registry modification, Choice.exe returns a value of 1. When the user presses the B key to select the New Batfile registry modification, Choice.exe returns a value of 2, and so on. The selected key's value is set to the ERRORLEVEL environment variable.
Because the selected key's value is set to ERRORLEVEL, the script uses the If ERRORLEVEL command to determine which key the user presses. However, when you use If ERRORLEVEL n (where n is the index number), all cases are selected when ERRORLEVEL is n or higher. To deal with this situation, you have two possible strategies. The first strategy is to use the syntax
If ERRORLEVEL n If Not ERRORLEVEL n+1 Goto :CodeLabel
where CodeLabel is the label for the code to which you want to proceed under that condition. Callout F in Listing 1 shows an example of what double If statements look like. The If statements can be listed in any order.
The second strategy is to drop the second If statement and put the If statements in reverse order. Listing 2 illustrates this alternative approach for the statements highlighted in callout F in Listing 1. This approach simplifies the code but also makes the order important. If improperly ordered, the code will fail. I chose to use the safer double If test in RegModsMenu.bat.
How to Use the Script
To get RegModsMenu.bat working in your environment, follow these steps:
Step 1. Install Choice.exe and Reg .exe on each computer on which you might use the script. (Reg.exe is built into Windows 2003 and is in the Windows 2000 Support Tools.) Alternatively, you can modify the script to use the tools from a remote shared folder, as the code at callout A in Listing 1 shows.
Step 2. Customize the registry modifications if needed. RegModsMenu .bat includes 21 registry modifications, but you might want to add more. The script currently uses 22 of the letters in the alphabet, so there are four unused letters to which you can assign new registry modifications. You can also use the numbers 0 through 9 and other characters, such as ( ) * % $ # @ ! ~ + - _ \ ' and ". So, if you use all the available letters, numbers, and characters, you can accommodate more than 40 registry modifications. If you make the letters case sensitive with the Choice command's /CS (Windows 2003) or /S (Win2K) switch, you can include another 26 registry modifications. Just be aware that it's easier to make an incorrect menu selection with case-sensitive options and thus make the wrong registry modification.
To add a registry modification, first create a labeled section of code that performs the desired registry change, using the existing subroutines at the end of RegModsMenu.bat as a template. Be sure to use a unique label name and test the code thoroughly. Next, add an Echo statement to the code at callout B. Then, add the new letter, number, or character to the Choice command in the code at callouts D and E. Finally, add a line to the If ERRORLEVEL section.
Conversely, you might find that some of the 21 registry modifications in the script aren't useful in your environment. For example, if you don't have Windows Update installed, it doesn't make sense to have the menu items that enable and disable it (items J and K, respectively). If that's the case, you can comment out or remove the appropriate code or replace it with modification code that's more useful to you.
Step 3. Test the script carefully on nonproduction computers that represent all the OSs in your environment to be sure the registry modifications accomplish the results you desire. I tested RegModsMenu.bat on Windows 2003, Windows XP Service Pack 1 (SP1) and SP2, and Win2K SP4 (SP4).
If you have Group Policy-applied settings that conflict with the settings you're applying with this script, you might find that the Group Policy-applied settings override the script's registry changes. This override might happen immediately, on the next reboot, or after the next refresh of the policy. Check your Resultant Set of Policy (RSoP) if you experience these types of problems.
Add Menus to Your Scripts
RegModsMenu.bat provides a simple yet safe way to store and deploy all your commonly used registry modifications. This script also illustrates how to use menus in scripts—a handy technique that you can apply to other scripts. For example, I added a menu to a script that runs nine common tools and internal commands used to diagnose PC and server problems. (You can read about this script in "Creating a Shell Scripting Tools Menu System," June 2003, InstantDoc ID 38666.) Whether you're deploying commonly used registry modifications, diagnostic tools, or other tools, using Choice.exe with the If ERRORLEVEL command lets you easily capture user input.