Windows Installer
The Windows Installer engine is really about configuration management. In conjunction with the MSI application database format, you can deliver just-in-time application installations that run in both system and user security contexts. The Installer service takes care of installing an application when the user invokes it, rather than relying on some disconnected software distribution mechanism to deliver machine-specific components at one time and user-specific components at another. MSI and the Windows Installer service are really the ideal way to deliver Registry changes. However, the downside is you have to package your changes using the MSI format. For small or frequent Registry changes, this is probably not the most efficient approach.
|
Tip: Consider the Windows Installer service when you have large application packages to deliver or you have the time to package your changes in a way that the
Installer service can leverage. |
One big advantage of using the Windows Installer in an AD environment is the ability to assign MSI packages to machines. When you assign a package to a machine via a GPO, you are in effect saying, "The next time this workstation reboots, run the installation represented by the MSI package I have assigned." This is a quick and easy way to install applications or even simple Registry packages at system boot time without user intervention and with LocalSystem security context.
Logging Issues
Even in Win2K, there are not many great native tools for logging changes. And depending on which tool you use to deliver changes, the logging mechanism may vary. There are a couple of basic ways you can log changes using the tools we have discussed. The first method works if you use simple batch scripts to deliver Registry changes.
For example, the following listing shows how Registry changes are logged using simple redirection.
REM * Script that logs changes to text file reg.log
@Echo reg add HKLM\Software\Myapp /v Default /d 10 >reg.log
reg add HKLM\Software\Myapp /v Default /d 10 >>reg.log
@Echo reg add HKLM\Software\Newapp /v InstallDir /d "c:\program files\
new app" >>reg.log
reg add HKLM\Software\Newapp /v InstallDir /d "c:\program files\
new app" >>reg.log
@Echo reg delete HKCU\Software\OldApp /f >>reg.log
reg delete HKCU\Software\OldApp /f >>reg.log
In this simple script, you see the redirection feature of NTs cmd shell (> and >>) used to redirect output of each .reg command line to a file called reg.log. Preceding each command, I echo what the command is actually doing to the log file, so I have a point of reference in my log file. The output of this script is shown here:
reg update add HKLM\Software\Myapp /v Default /d 10
The operation completed successfully
reg add HKLM\Software\Newapp /v InstallDir /d "c:\program files\new app"
The operation completed successfully
reg delete HKCU\Software\OldApp
The operation completed successfully
This script shows the importance of choosing Registry tools that do some kind of reporting on success. With a simple tool such as Regedit, this is its biggest downside. You really dont get much information about whether it succeeded or failed. And if you have a .reg file that makes many changes, you have no idea whether one or ten of them failed or succeeded. (You would have to look at the keys you tried to change to be sure whether a change occurred.)
You can also use NTs event log for logging. The Resource Kit comes with the Logevent.exe tool, which allows you to generate your own events. The following listing shows an example of how you can use logevent.exe to logged failed changes to the Registry.
Reg add HKLM\Software\myapp\ /v default /d 10
If errorlevel 1 logevent --s F --r "Reg script" --e
9999 "Attempt to Update MyApp key failed"
The listing takes advantage of the fact that Reg returns an errorlevel (in this case, 1) if it fails to complete. Based on that errorlevel, I use the logevent utility to write an event to the Application event log on the system where the script ran. Figure 1 shows the resulting event log entry using the script above.
Note: In the script above, I chose an arbitrary event ID of 9999 and arbitrary Source called "reg script" to easily identify my events. Logevent also supports sending the event to another machines event log, which could be a central collection point for the results of this script on many systems. For example, line 2 c.ould say:
If errorlevel 1 logevent --m \\logsever.mycompany.com --s F --r "Reg script" --e
9999 "Attempt to Update MyApp key on %computername% failed"
In this case, logserver.mycompany.com is a central server that collects logs from many machines. Note that, in my error text, I added the environment variable %computername% to report back the name of the target device where the script failed. |
If you use the Windows Installer to install applications on your workstations, you can use the logging features available within it to find out whats going on during application installation. You can enable verbose logging of software installation via a Group Policy Administrative Template. In Computer Configuration\Administrative Templates\Windows Components\Windows Installer, there is an option to enable logging. When you enable logging, you also have the option of controlling the verbosity of the log file (Figure 2).
When it comes to logging, the bottom line is to choose Registry tools such as Reg, Regini, and the Windows Installer, which make it easy for you to gather status on the execution of the changes. Proper configuration management depends on the ability not only to deliver changes to many systems, but also to know how successful those changes are.
Using Windows Scripting Host to Modify the Registry
First introduced as an add-on in NT 4.0, WSH is now an integral part of Win2K. The idea was to take the scripting container available in Internet Explorer and make it available outside of the Web context, as a standalone, command-line or GUI-based scripting host. WSH is language-independent. That is, you can use practically any scripting engine to write WSH scripts.
WSH provides a set of COM objects that you can manipulate to perform some basic Explorer Shell and Windows API functions. In addition, it also supports other objects and methods provided by ActiveX controls that have been installed on your system. In Win2K, WSH comes with support for VBScript and JScript engines. Third-party vendors provide support for other engines, such as Perl and REXX. For the purposes of our discussion, I give examples only in VBScript. However, anything I show here could be done in the scripting language of your choice.
The material presented assumes that you have some knowledge of Visual Basic (VB) or VBScript (VBScript is a subset of the functionality found in the full VB language set). I dont tell you how to write VBScript, but rather explain and illustrate some of the Registry-related methods available through the WSH.
When it comes to using the WSH for Registry changes, the amount of information you need to know is pretty small. By default, the WSH offers you exactly three methods for manipulating the Registry. They are
- RegDelete
- RegRead
- RegWrite
The WSHShell object provides these three methods. Although they may not seem that significant, remember that the ability to use a scripting engine like VBScript or JScript to process your Registry changes means that you also get all of the capabilities each of these languages provides — such as conditional statements, looping, subroutines, and error handling.
WSH script files take the extension of the language they are written in and associated with. For example, VBScript files should have a .vbs extension and JScript files should have .js extension. When a WSH file has one of these extensions, you can launch it simply by double-clicking on it within the file Explorer. A third file type — .wsf or Windows Script Files — use an XML-based format and can contain either JScript or VBScript code.
The WSH provides two different interpreters from which to launch script files — wscript.exe and cscript.exe. The functional differences between the two are few. Cscript is called from a command shell, whereas wscript is usually called by file association. One significant difference is the way each presents output. If I use the Echo method in my script to echo a message to the user and I invoke the script using wscript.exe, the message is displayed in a dialog box. However, if I invoke the script using cscript from a command shell, the message is displayed to the command shell as text without any popup dialogs. Otherwise, scripts generally execute the same way using either version. In the simplest example, to launch a WSH script from the command-line, type Cscript myscript.vbs.
In a default Win2K configuration, wscript.exe is associated with .vbs, .wsf, and .js files. However, both support the same options at runtime. For example, both can take a number of command-line parameters to modify the behavior of the script. One option I find extremely useful is the //t:## option, which lets you specify the maximum time in seconds that a WSH script can run. This prevents runaway scripts from consuming all available system resources if there are bugs in the code. To use this option, you would type Cscript (or wscript) //t:10 myscript.vbs.
In this example, the WSH script called myscript.vbs would run for 10 seconds (Note that command-line options are delineated with a double slash rather than a single one). After 10 seconds, the script would terminate, regardless of whether it completed. If you type cscript (or wscript) /?, you can get a list of all of the available command-line options.
To illustrate how you can use VBScript and the WSH to manipulate the Registry, Figure 3 exercises each of the above three methods to perform Registry operations — in this case, disabling the Auto Admin Logon feature if it is enabled.
Lets examine this script. The first major thing it does, in Line 7, is instantiate the WSHShell object. This step is required in WSH scripts that intend to use the Wscript.Shell methods, such as the Registry set of methods. Line 9 uses the RegRead method to get the data contained in the AutoAdminLogon value within HKLM. Line 11 does the same thing to obtain the DefaultPassword value. Line 14 tests to see whether the variable strAutoLogon is set to 1 (meaning AutoAdminLogon is enabled). If so, the script pops up a message box indicating that it is preparing to disable this feature. Line 16 uses the RegWrite method to change the value from 1 to 0.
Line 18 checks to see whether the DefaultPassword value is nonblank. If so, Line 19 warns that the Default Password is about to be removed, then Line 20 uses the RegDelete method to remove the value from the Registry. Finally, Line 23 exits the script and returns an errorlevel of 0 to indicate that it completed successfully.
This simple example shows how you can use the WSH to script Registry changes that take advantage of the best features of your favorite scripting language. A couple things to note about the three Registry methods in WSH. First, supported Registry path abbreviations include HKLM, HKCU and HKCR. You can get to HKEY_USERS and HKEY_CURRENT_CONFIG by spelling out their names directly (e.g., RegRead("HKEY_USERS\.Default). If you enter a Registry path that does not exist, or cant be found, the WSH returns a rather confusing error — namely that the "system cannot find the file specified." This simply means that the Registry key or value doesnt exist or that you entered the path incorrectly. Also, the Registry methods dont support reading a remote machines Registry. This limitation, unfortunately, makes WSH less useful as a Registry tool.
Note: I can comment my scripts using the apostrophe (Ô) at the beginning of or within a line. For example, Line 23 could say
Wscript.Quit(0) Ôthis line exits the script and returns a 0 if
everything runs ok |
The following listing shows another simple way of using a WSH script to extract Registry information. In this case, I use VBScript to query a Registry value in HKEY_CURRENT_USER that holds the server name my workstation currently uses to authenticate to the AD. I could deliver this to my users to let them get this information interactively using wscript.exe or invoke it from a remote command shell to find out the information remotely using cscript.exe.
1. Declare variables
2. Dim WSHShell,strRegKey
3. Create the Wscript Shell object, which contains the Registry methods
4. Set WSHShell = WScript.CreateObject("WScript.Shell")
5. strRegKey="HKCU\Volatile Environment\LogonServer"
6. WScript.Echo "Current Logon Server is: " & WSHShell.RegRead(strRegKey)
7. Wscript.quit(0)
If we follow this simple script, Line 4 instantiates the familiar Wscript.Shell object, which contains the Registry methods we need. In Line 5, I set a variable that points to the Registry value of interest. In larger scripts in which you need to access the same Registry path in many areas of the script, this is a quick shortcut that makes your life easier. Finally, in Line 6, I use the Wscript method called echo to report out the Current Logon Server, which calls the RegRead method on my variable to the Registry path. The techniques in this script are common ones that you use over and over in Registry scripting using the WSH.
Microsoft Script Debugger
Win2K comes with a basic scripting debugger that you can use to do some rudimentary troubleshooting of your WSH scripts. It is not installed by default, but you can choose it as an option from the Add/Remove Programs Control Panel applet. If you write a WSH script that encounters an error at runtime, the default behavior is that cscript or wscript fires up the Microsoft Script Debugger to help you troubleshoot your WSH application. Figure 4 shows an example of the Script Debugger running against a WSH application that I wrote.
The Microsoft Script Debugger is a basic tool not meant to replace a good visual development environment. However, for basic troubleshooting, with the ability to set breakpoints in your script, and for basic editing, it is useful. If you want to start it interactively, without invoking it via a scripting error, execute c:\program files\Microsoft Script Debugger\msscrdbg.exe.
Summary
In this chapter, we discussed how to deliver Registry scripts to multiple machines at once using techniques such as logon, logoff, startup, and shutdown scripts, and the WSH. When you deliver Registry changes via script, there are three things keep in mind. First, does the script have the proper security context to perform the change? Second, will the change be delivered at the right time (i.e., Is the Registry key or value available when the script runs?). Finally, how do I know that the script completed properly? You are able to log your Registry script changes.
|