Implementing the Penton.RegObject object
In "Registry Reading and Writing Made Simple, Part 1" (October 2005, InstantDoc ID 47540), I introduced you to the Penton.RegObject object. With this object, you can easily handle Windows Management Instrumentation's (WMI's) StdRegProv class methods. In "Registry Reading and Writing Made Simple, Part 2" (November 2005, InstantDoc ID 47736), I showed you how to use the Penton.RegObject object to read and write registry values in both VBScript and JScript code. The object's properties and methods provide easy access to the registry on the local or a remote computer. In Part 3, I present RunMgr.js, a JScript script that lets you manage the values in the Run registry key on local or remote computers.
Understanding the Run Registry Key
The Run registry key is one of many program startup locations that Windows checks when a user logs on to the system. In Windows XP and later, you can run the Msconfig utility and click the Startup tab to display the entries in the Run registry key. For a flexible utility that shows a more comprehensive list of startup locations, I recommend Sysinternals' Autoruns utility. (See "Autoruns," InstantDoc 44089, for a description of this useful tool.) You'll find the Run registry key at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. The programs listed in this key are executed at logon before the programs listed in the Startup folder.
RunMgr.js is a JScript script that lets you manage the values in the Run registry key on local or remote computers from the command line. To run the script, you must have JScript 5.6 or later. On Windows 2000, JScript 5.6 is installed with Microsoft Internet Explorer (IE) 6.0 or later. You can also download the standalone installer (scripten.exe) from the Microsoft Web site. JScript 5.6 is already included with XP and later OSs.
The script also requires that RegObject.wsc be registered on the system that executes the script. For information about how to register the RegObject.wsc component, see Part 2 of this series.
The RunMgr.js command-line syntax is
\[cscript\] RunMgr.js \[computername\] \[/list | /exists:value | /add:name=value | /delete:value\]
Because RunMgr.js requires the CScript host, use the cscript keyword at the beginning of the command line if CScript isn't your default script host. (All the other command-line parameters can appear in any order.)
To make CScript your default script host, type the following command at a command prompt:
cscript //h:CScript //nologo //s
Note: Although the above command could be simply
I include //nologo and //s to reduce screen clutter. The //nologo option prevents the display of the Windows Script Host (WSH) copyright message every time you run a script that uses CScript. The //s option saves this change.
The computername argument specifies a remote computer name, if one is needed. If you don't specify the computername parameter, the script uses the local computer. None of the options are case sensitive.
The /list option lists the data in the Run registry key. Figure 1 displays the registry values and contents.
The /exists option lets you check for the existence of a registry value. The script returns an exit code of 1 if the value exists and an exit code of 0 if it doesn't exist. For example, if the registry values are those that Figure 1 shows, the following command causes the script to return an exit code of 1 (the value exists):
The /add option adds an entry to the Run key. The name parameter is simply an arbitrary string that describes the executable. Because the string must be unique to the Run key, a good choice is the name of the executable you're running. The value parameter specifies the name of the executable and any command-line arguments it requires. RunMgr.js contains code that converts single quotation marks (') to double quotation marks (") for value. This feature lets you specify quoted strings inside the value parameter. The script also uses the REG_EXPAND_SZ data type for value, so you can use environment variables if you double the percent symbols (%). For example, the following command adds the value SetDefaultPrinter to the registry and executes the command line "%ProgramFiles%\sdp.exe" "\\PS\My Printer":
runmgr.js /add:SetDefaultPrinter= "'%%ProgramFiles%%\SDP\sdp.exe' '\\PS\My Printer'"
Note that the entire value parameter is enclosed in double quotation marks.
The /delete option deletes the specified value from the registry. For example, to delete the sample value created in the previous example, use the command
RunMgr.js begins by declaring its global variables. It then adds prototype methods to the JScript Array and String objects. Doing so lets the script call these methods for any Array or String objects. (For information about using the prototype property to extend objects, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/js56jsproprototype.asp.) RunMgr.js then calls the WScript object's Quit method, using the return value for the main function as its exit code.
The main function. The main function first declares the variables it will use. Next, it assigns the allargs and namedargs variables to the WScript.Arguments and WScript.Arguments.Named collections, respectively. Named arguments are any arguments on the command line that begin with a forward slash (/). If no named arguments were specified or if the /? argument was specified, the script calls the usage function, which displays a short usage message and ends the script.
Next, the main function checks whether the command line has any unnamed arguments (i.e., arguments that don't start with a forward slash). If the command line has no unnamed command-line elements, the computername variable will contain a dot (.), which refers to the local computer.
The function then checks the script host by calling the scripthost function, which returns the script host executable's name. If the name isn't cscript.exe, the script aborts with an error message and a nonzero exit code.
Checking for valid command-line arguments. Callout A in Listing 1 shows how the main function validates the script's command-line arguments. First, the function creates an array containing a list of valid named arguments. Next, it creates a JScript Enumerator object to iterate the WScript.Arguments.Named collection. For those unfamiliar with JScript, JScript's for statement doesn't enumerate collections in the same way that VBScript's For ... Each statement does. To enumerate collections in JScript, you create an enumerator object. You can then use the for statement and the Enumerator object's MoveNext method to iterate the collection. The item method returns the current item.
Inside the for loop, the arg variable is assigned a lowercase copy of the current item in the collection (i.e., the arg variable will contain a copy of the command-line argument that has been converted to lowercase). If the current item in the collection exists in the array of valid arguments, the valid variable (a Boolean) will contain True. If arg contains the string "list", the break statement exits the for loop (the /list option doesn't require any parameters).
All the command-line options except /list require a parameter. If /exist or /delete is specified, that command-line option must have a value parameter. Without that parameter, the valid variable will contain False. When the valid variable contains False, the script will be aborted with an error message and a nonzero exit code. If /add is specified, the script uses the leftofdelim and rightofdelim functions to determine whether a name=value parameter is included.
Connecting to the computer. Callout B shows how the main function creates an instance of the Penton.RegObject object, then the object uses its Connect method to connect to the computer. If the result is nonzero, the script exits with an error message and a nonzero exit code.
Accessing the registry. Callout C shows how the main function uses JScript's switch statement to decide which block of code to execute according to the specified command-line parameter:
- /list uses the Penton.RegObject object's EnumValuesAndData method to enumerate the values in the Run key. After calling this method, the Penton.RegObject object's EnumDict property references a Scripting.Dictionary object containing the Run key's values and data. The main function calls the Penton.RegObject object's dictToJSArray method to copy the Scripting.Dictionary object into a JScript array, which can be iterated by using JScript's for statement.
- /exists uses the Penton.RegObject object's ExistValue method to determine whether the specified value name exists. If the result is True (the value exists), the result variable contains 1; otherwise, it contains 0.
- /delete uses the Penton.RegObject object's DeleteValue method to delete the specified registry value.
- /add adds the specified name=value pair to the registry. The main function uses the String object's replace method to convert single quotation marks to double quotation marks. It then uses the Penton.RegObject object's WriteValue method to write the data to the registry. Note that the main function uses the leftofdelim function to determine the name part of the argument and the rightofdelim function to determine the value part of the argument. It also writes the data using the REG_EXPAND_SZ data type.
In addition, note the use of break statements after each block of code the case statements specify. Unlike when you use VBScript's Select Case statement, execution flows to the next case block unless you use a break statement.
Taking Control of the Run Registry Key
RunMgr.js provides a good example of how simple it is to use the Penton.RegObject object to manage the registry, even from JScript code. You can use RunMgr.js to manage the Run registry key on any computer on your network.