|
|
Scripts give IT professionals the ultimate ability to control and automate Windows XP. These aren't batch files; they're full-fledged administrative programs that are surprisingly easy to create considering the wealth of power they enable. You can write a script that inventories a computer and writes the result to a file on the network, for example. You can automate an application to perform redundant steps automatically. The sky is the limit, really, but I'm here to tell you how to use scripts to edit the registry, so I'm confining myself a bit.
The scripting technology in Windows XP is Windows Script Host. The current version is 5.6 and is technologically leaps and bounds over what Microsoft Windows 2000 provided. Windows Script Host is called a host because it's not aware of a script's language. Microsoft calls this language agnostic. Windows Script Host uses different scripting engines to parse the different languages in which you might write a script. Windows XP provides two scripting engines: VBScript and JScript. If you've ever used the C or C++ languages, you'll be more comfortable writing scripts using JScript. If you've ever used Visual Basic in any of its incarnations, you're going to be more comfortable using VBScript to write scripts.
The problem with focusing this chapter on how to use scripts to edit the registry is that doing so assumes that you're already familiar with Windows Script Host. If that's not true, I suggest that you find a good book about scripts. If you don't want a book about it, see http://www.microsoft.com/scripting. This is Microsoft's Scripting Web site, and it contains everything you need to know about writing scripts for Windows XP, including accessing Windows Management Instrumentation (WMI) through scripts. After you've mastered the languages, which aren't difficult, you'll appreciate this Web site's reference content. The content describes the object model and how to use it—the hardest part of writing scripts for Windows XP.
Script files can have two file extensions, and the script's file extension indicates which language the file contains. Use the .js extension for files that contain JScript. Use the .vbs extension for files that contain VBScript. Regardless, script files are nothing more than text files that contain the language's keywords, so you can use your favorite text editor, Notepad, to create them. When you save a script file, make sure you enclose the file's name in quotation marks or choose All Files from the Save As Type list so Notepad doesn't add the .txt extension to the file.
Without going into detail about the object model, you access the registry through the Shell object. This object contains the methods you call to add, remove, and update values in the registry. You'll add one of the following statements to every script in which you want to access the registry. The first line shows you how to create the Shell object using VBScript, and the second shows you how to do it using JScript. Just to show you how easy it is to create a script, open Notepad, and type Listing 9-7. The JScript language is case sensitive, so type Listing 9-7 carefully. VBScript has the benefit of not being case sensitive. Save the file using the .js extension, and then double-click the file to run it. You'll see a message from me. Because double-clicking the script file runs it, you must right-click the file and then click Edit to edit the file.
Listing 9-7: Example.js
var WshShell = WScript.CreateObject("WScript.Shell"); WshShell.Popup("Hello from Jerry Honeycutt" );
set WshShell = WScript.CreateObject("WScript.Shell") var WshShell = WScript.CreateObject("WScript.Shell");
I usually write INF files to edit the registry. If I'm not using INF files, I write batch files and use Reg.exe. I like the simplicity of these methods. There are times when writing a script is the only suitable method, however.
Writing a script is necessary in a number of cases. The first is when you must have a user interface. If you want to display settings to or collect settings from users, scripting is the best choice. Also, scripting is the only method that provides rather full access to Windows XP. For example, you can use a script to inventory the computer and dump the information to a text file on the network. You can use a script to configure users' computers using logic, if-this-then-that, which isn't possible with the other methods. So if you're doing anything more complicated than just adding, changing, or removing values, you're going to end up writing scripts. I've seen some fairly complicated scripts. For example, one fellow I worked with wrote a script that searched the registry for services that Sysprep disabled, and then permanently removed them from the registry. This is a great example of scripting.
Combined with WMI, scripting is nothing short of amazing. The script on the next page shows you how to use VBScript and WMI to inventory a computer's configuration. It displays the amount of physical memory installed on the computer, the name of the computer, the BIOS version, the type of processor, and more. This script and many more like it are available on Microsoft's Script Center, which is a large library of scripts that you can download, modify, and use. All these scripts are at http://www.microsoft.com/technet/scriptcenter.
strComputer = "." Set objWMIService = GetObject("winmgmts:" _ & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Set colSettings = objWMIService.ExecQuery _ ("Select * from Win32_OperatingSystem") For Each objOperatingSystem in colSettings Wscript.Echo "OS Name: " & objOperatingSystem.Name Wscript.Echo "Version: " & objOperatingSystem.Version Wscript.Echo "Service Pack: " & _ objOperatingSystem.ServicePackMajorVersion _ & "." & objOperatingSystem.ServicePackMinorVersion Wscript.Echo "OS Manufacturer: " & objOperatingSystem.Manufacturer Wscript.Echo "Windows Directory: " & _ objOperatingSystem.WindowsDirectory Wscript.Echo "Locale: " & objOperatingSystem.Locale Wscript.Echo "Available Physical Memory: " & _ objOperatingSystem.FreePhysicalMemory Wscript.Echo "Total Virtual Memory: " & _ objOperatingSystem.TotalVirtualMemorySize Wscript.Echo "Available Virtual Memory: " & _ objOperatingSystem.FreeVirtualMemory Wscript.Echo "OS Name: " & objOperatingSystem.SizeStoredInPagingFiles Next Set colSettings = objWMIService.ExecQuery _ ("Select * from Win32_ComputerSystem") For Each objComputer in colSettings Wscript.Echo "System Name: " & objComputer.Name Wscript.Echo "System Manufacturer: " & objComputer.Manufacturer Wscript.Echo "System Model: " & objComputer.Model Wscript.Echo "Time Zone: " & objComputer.CurrentTimeZone Wscript.Echo "Total Physical Memory: " & _ objComputer.TotalPhysicalMemory Next Set colSettings = objWMIService.ExecQuery _ ("Select * from Win32_Processor") For Each objProcessor in colSettings Wscript.Echo "System Type: " & objProcessor.Architecture Wscript.Echo "Processor: " & objProcessor.Description Next Set colSettings = objWMIService.ExecQuery _ ("Select * from Win32_BIOS") For Each objBIOS in colSettings Wscript.Echo "BIOS Version: " & objBIOS.Version Next
Windows XP provides two scripting hosts. The Windows-based version runs scripts when you double-click a script file. The script engine is Wscript.exe. You can also use the command-line version, which is handy when the script outputs data similar to how most command-line programs do. The example given in the sidebar "Why write scripts when INF files are easier?" in Listing 9-7 is one script that's better from the command-line. The command-line scripting engine is Cscript.exe:
cscript script [//B|//I] [//D] [//E: engine] [//H:cscript|//H:wscript] [// Job:name] [//Logo|//Nologo] [//S] [//T:time] [//X] [//?]
//B | This specifies batch mode, which does not display alerts, scripting errors, or input prompts. |
//I | This specifies interactive mode, which displays alerts, scripting errors, and input prompts. This is the default and the opposite of //B. |
//D | This turns on the debugger. |
//E: engine | Specifies the scripting language that is used to run the script. |
//H:cscript | //H:wscript | This registers either Cscript.exe or Wscript.exe as the default script host for running scripts. If neither is specified, the default is Wscript.exe. |
//Job: name | This runs the job identified by name in a .wsf script file. |
//Logo | This specifies that the Windows Script Host banner is displayed in the console window before the script runs. This is the default and the opposite of //Nologo. |
//Nologo | This specifies that the Windows Script Host banner is not displayed before the script runs. |
//S | This saves the current command-line options for the current user. |
//T: time | This specifies the maximum time the script can run (in seconds). You can specify up to 32,767 seconds. The default is no time limit. |
//X | This starts the script in the debugger. |
//? | This displays available command parameters and provides help for using them. (This is the same as typing Cscript.exe with no parameters and no script.) |
You can specify some of the same options when using the Windows-based scripting host. Right-click the script file, and then click Properties. You'll see the dialog box shown in Figure 9-3 on the next page. You can set the amount of time that the script is allowed to run and whether or not the host displays a log. The result is a file with the .wsh extension that contains these settings. It looks like your average INI file. You then execute the script by double-clicking the WSH file.
Figure 9-3: You create a WSH file, which contains a script file's settings, by right-clicking the script, clicking Properties, and then clicking the Script tab.
Before I show you how to edit the registry with a script, there's one more detail: how to format the names of keys and values in a script. Unlike other scripting methods I've described in this chapter, the Windows Script Host object model doesn't have separate parameters for the key and value name. Thus, you distinguish key names and value names by how you format them. The rule is simple: If a string ends with a backslash, it's a key name; if a string doesn't end with a backslash, it's a value name. Also, the JScript language reserves the backslash character (\) as the escape character: \n is a newline character and \t is a tab, for example. That means that you must escape the backslashes in your keys. Thus, any time you have a backslash in a key, you must use two backslashes (\\). To keep these clear, see Table 9-4.
Object | VBScript | JScript |
---|---|---|
Value | "HKLM\Subkey\Value" | "HKLM\\Subkey\\Value" |
Key | "HKLM\Subkey\" | "HKLM\\Subkey\\" |
The Shell object's RegWrite method adds keys and values or changes existing values. If you want to change a key's default value, set strName to the name of the key, including the trailing backslash, and then assign a value to it.
Tip | One of the RegWrite method's biggest weaknesses is that it writes only four bytes of REG_BINARY values. It can't handle larger binary values. If you want to change longer binary values or change types of values that this method doesn't support, use the Shell object's Run method to import a REG file. For example, you can put your settings in a REG file called Settings.reg. Then import that REG file using the statement WshShell.Run("Settings.reg"). |
object.RegWrite( strName, anyValue [,strType] )
object | This is the Shell object. |
strName | This is the string indicating the name of the key or value. You can add keys. You can add or change values. strName must be a fully-qualified path to a key or value and begin with one of the root keys: HKCR, HKCU, HKLM, or HKU. |
anyValue | This is the data to assign to new or existing values. Use the format appropriate for the value's type. |
strType | This is the type of value to create: REG_SZ, REG_EXPAND_SZ, REG_DWORD, or REG_BINARY. The RegWrite method doesn't support the REG_MULTI_SZ value type. Also, this method writes only four byte REG_BINARY values. |
Set WshShell = WScript.CreateObject("WScript.Shell") WshShell.RegWrite "HKCU\Software\Sample\", 1, "REG_BINARY" WshShell.RegWrite "HKCU\Software\Sample\Howdy", "World!", "REG_SZ"
var WshShell = WScript.CreateObject( "WScript.Shell" ); WshShell.RegWrite("HKCU\\Software\\Sample\\", 1, "REG_BINARY"); WshShell.RegWrite("HKCU\\Software\\Sample\\Howdy", "World!", "REG_SZ");
The Shell object's RegDelete method removes keys and values from the registry. Be careful, however, because removing an entire branch is easy; there's no confirmation. To remove a key, end strName with a backslash; otherwise, you're removing a value.
object.RegDelete( strName )
object | This is the shell object. |
strName | This is the string indicating the name of the key or value to delete. strName must be a fully qualified path to a key or value and begin with one of the root keys: HKCR, HKCU, HKLM, or HKU. |
Set WshShell = WScript.CreateObject( "WScript.Shell" ) WshShell.RegDelete "HKCU\Software\Honeycutt\Howdy" WshShell.RegDelete "HKCU\Software\Honeycutt\"
var WshShell = WScript.CreateObject( "WScript.Shell" ); WshShell.RegDelete ( "HKCU\\Software\\Honeycutt\\Howdy" ); WshShell.RegDelete ( "HKCU\\Software\\Honeycutt\\" );
The Shell object's RegRead method returns a value's data. To read a key's default value, end strName with a backslash; otherwise, you're reading a value.
object.RegRead( strName )
object | This is the shell object. |
strName | This is the string indicating the name of the value to read. strName must be a fully qualified path to a key or value and begin with one of the root keys: HKCR, HKCU, HKLM, or HKU. |
Dim WshShell, dwFlag, strValue Set WshShell = WScript.CreateObject( "WScript.Shell" ) dwFlag = WshShell.RegRead( "HKCU\Software\Honeycutt\" ) strValue = WshShell.RegRead( "HKCU\Software\Honeycutt\Howdy" )
var WshShell = WScript.CreateObject( "WScript.Shell" ); var dwFlag = WshShell.RegRead( "HKCU\\Software\\Honeycutt\\" ); var strValue = WshShell.RegRead( "HKCU\\Software\\Honeycutt\\Howdy" );
|
|