This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
|
cutting@microsoft.com Download the code (3KB) |
Dino Esposito |
What is the Windows Scripting Host?
Suppose you want to create a shortcut on the desktop and you want to do it repeatedly in a batch-mode, non-interactive way. You could write a utility to automate this task, but that would require knowledge of the low-level shell's object model and registry details, not to mention familiarity with COM programming. Writing the utility would take a while to complete and might not be worth the effort.
With WSH, a parser engine for script languages is embedded in the Windows desktop, as well as in Microsoft Internet Explorer and Internet Information Server. Functionally speaking, the parsing modules found in each host are nearly the same. What changes is the surrounding object model: Dynamic HTML for Internet Explorer 4.0 and the Windows Scripting Host model for the desktop. Moreover, in the Windows desktop a script is identified through its extension (.vbs for VBScript or .js for JScript). This lets you associate shell facilities like additional property sheet pages and context menu items with scripts, as shown in Figure 1. It also means you can double-click a .vbs or .js file in Windows Explorer (or single-click, depending on your Active Desktop settings) to run the specified script. In other words, you can consider .vbs and .js new executable extensions, just like the old .bat files.
Running Scripted Batches
"Scripted batch" is not a standard expression. However, I think it's a good way to think of WSH. The scripting host exposes an object model that renders a portion of the Windows desktop. The script language is a flexible and powerful tool to leverage such objects, giving you the same simple approach provided by MS-DOS batch files.
There are two ways to run such script files. The first is by invoking the command-based scripting host (cscript.exe). The syntax is:
cscript filename [//options] [/arguments]
The options refer to features of WSH such as the working mode (interactive or batch) and whether to display the banner at execution time. They are the arguments of the cscript.exe engine, and are all prefixed by double slashes.
cscript myScript.vbs //I //logo
The cscript command-line options are listed in Figure 2. (wscript.exe offers the same options with one difference: it doesn't suppport the logo and nologo options.) After the scripting host options, you provide the arguments you want the script itself to receive through the command line. Each script argument is prefixed with a single slash.
There are very few differences between cscript and wscript. Cscript is a console-based application and runs inside an MS-DOS box (see Figure 3). The first two lines displayed are the banner, a feature you can turn on and off using the logo and nologo options discussed earlier. The example shown in Figure 3, shortcut.vbs, is provided with the WSH package. It creates a shortcut to Notepad on your desktop. As you can see, this script is interactive and prompts the user for confirmation. If you try to run it this way
cscript shortcut.vbs //B
it won't work because the //B argument suppresses the interactive operations.
You can stop any script that is running inside the WSH after a specified number of seconds. This is to prevent poorly designed or overly greedy scripts from consuming too many machine cycles. The ActiveX Scripting engine actually kills the script, and this operation is generally safe. The InterruptScriptThread function, which is a method exposed by the IActiveScript COM interface, accomplishes the program interruption.
The Role of WSH Files
I mentioned earlier that .vbs and .js files have an additional property page associated with them. If you modify the settings presented in the page and apply the changes, the system automatically creates a file with the same name as the script but with a .wsh extension. A .wsh file is an ASCII file that follows .ini file conventions. Here's a typical example:
[ScriptFile]
Path=C:\SHORTCUT.VBS
[Options]
Timeout=10
DisplayLogo=1
BatchMode=0
The file stores user preferences such as interactive or batch mode, and gives system administrators a way to let different users run the same script with different settings.
The WSH Object Model
WSH is a small application that hosts an ActiveX Scripting engine, just as Internet Explorer does. In his Extreme C++ column (MIND, August 97), Steve Zimmerman demonstrated how applications could host such engines and support VBScript or JScript-based programs. Microsoft recently released the Script Control for this purpose. WSH works the same way; cscript and wscript simply interpret script files and pass them to the various IactiveScriptXXX interfaces. WSH identifies the proper scripting engine to load by looking at the file extension. The scripting engine integrated into Internet Explorer relies on the LANGUAGE attribute of the <SCRIPT> tag to get the same information.
WSH helps you manipulate any automation object installed on your machine. It also defines its own object model, which is somewhat similar to the Windows desktop. There are three basic tasks you can perform with WSH: handling WSH objects and ActiveX objects, manipulating the registry, and accessing the file system through FileSystemObject. Under Windows NT 5.0, you can also use WSH to access the Windows NT Active Directory service.
There are three main objects in the WSH object model: WScript, WshShell, and WshNetwork (see Figure 5). WScript renders the entire scripting host. WshShell and WshNetwork are helper objects that map some functions of the Windows shell and the network. For example, they let you map and unmap printers and remote drives and manipulate the registry. These three objects must be created via their ProgIDs or CLSIDs, just like any other COM object.
The WScript object exposes properties that tell you the path of the running scripting host (wscript.exe or cscript.exe), its arguments, and the working mode (interactive or batch). The WScript object also provides methods to create and read objects.
The shell object is a bit more interesting. While it doesn't expose all the properties and methods you could imagine or desire, WshShell does allow you to start a new process and create shortcuts. It also provides the Environment collection to handle environmental variables such as WINDIR, PATH, or PROMPT.
|
Note that some older documentation speaks of methods such as GetEnvironmentVariable or DeleteEnvironmentVariable. They no longer exist. Instead, the Environment property object points to a collection of variables. This collection has an Item property through which you can attain the state of the system environment. The Environment object exposes the usual collection methods and properties such as Item, Count, and Length, plus a Remove method for removing an environmental variable: |
|
Count and Length both return the number of elements included in the specified collection. WSH supports both for compatibility purposes. The ExpandEnvironmentStrings method can format strings that include environmental variables if they are bracketed by % characters: |
|
The Windows shell contains a number of special system folders such as Desktop, Start Menu, and Send To. The actual paths to these folders are returned by the SpecialFolders method (I'll discuss this more later). The Run method has an interesting feature. The syntax is: |
|
The strCommand parameter is the command line for
the process to be created, while iWindowsType defines the status of the window. bWaitOnReturn is a pleasant surprise; you can control a script's synchronization by setting it to FALSE or TRUE. If you want your script to wait for the spawned process to terminate, then set that argument to TRUE. By default, the new process starts while the script continues its execution. The WshNetwork object maps the network, making it easy to connect and disconnect remote drives and printers. In addition, it provides easy-to-use properties for obtaining information about the current user and profile. The following snippet will echo the current computer name and user name: |
|
Underneath the objects I've discussed, there are a few other objects that are not exposed to programmers directly via a ProgID. A list of these objects is shown in Figure 6. Among them you can find a WshShortcut object that presents all the features of a desktop shortcut, including the working directory, the target path, the hotkey, and the default icon. A shortcut is returned by the shell's CreateShortcut method. Other minor objects include the WshArguments collection, which holds the list of arguments for the script, and WshEnvironment, which contains environmental variables. Except for the WScript object, which is always running, the exposed objects must be created each time you need them. You can use familiar names to access the shell and network classes instead of memorizing ProgIDs: |
|
The WScript object is contained in both wscript.exe and cscript.exe (which is why it's always running). All other WSH objects are implemented in a COM automation component, wshOM.ocx, in the Windows system directory. When creating a new object you have two choices. You can use WScript.CreateObject and rely on the WSH root object to create your object, or you can use the VBScript CreateObject function or the JScript built-in ActiveXObject. Which is the faster method? My tests suggest that the CreateObject/ActiveXObject method is slightly faster and requires less memory. This is to be expected; since the scripting engine is already running, asking it to create a new object shouldn't introduce any additional overhead.
Creating Shortcuts
|
|
This will give you a .lnk file that contains all the information needed to point to Notepad.exe. This operation is performed in
a snap and without any user
intervention. Using the same technique, you could also add new items to the Start menu. Here's a VBScript sample that adds the Paint program (mspaint.exe): |
|
Manipulating the Registry
|
|
This code writes a DWORD value into a new or existing value called DisableRegistryTools, which is located on the registry path HKEY_USERS\Default\Software\Microsoft\Windows\
CurrentVersion\Policies\System\. RegWrite supports only a few types: REG_DWORD, REG_ SZ, REG_BINARY, and REG_EXPAND_SZ. Any necessary conversions are performed by the shell object method because neither VBScript nor JScript recognize data types. To support more types, you might want to write your own component to edit the registry. You can access a remote registry using the Win32 RegConnectRegistry API function. The listing shown in Figure 8 uses the RegWrite method to define a popup message that will be displayed during the logon process. The RegWrite method exposed by the WshShell object lets you access any key within the system registry and write any of the most common types of data. You can create new keys, too. The WSH objects let you, as a system administrator, use script code to quickly customize the appearance and function of a connected workstation. You could also use a .reg file for the registry manipulation, but the scripting method offers a more readable syntax, along with a flexible and powerful language.
Accessing Generic COM Servers
|
|
This code shows the first document in the Microsoft Word recent file list. The samples available on the Microsoft Scripting site also include a demonstration of driving Microsoft Excel documents from within WSH. Another interesting example is the following: |
|
This runs the standard Find Files system dialog you see when you select the Find | Files or Folders item from the Start menu. Through WSH you can easily access the local file system through FileSystemObject. This lets you create directories, obtain information about available disk space, and even create and edit files. To perform basic operations such as creating a new directory, you can take a couple of approaches. One approach is to ask the shell object to run command.com: |
|
If you do this, be certain to specify the full path for the new directory. Otherwise, it will be created under the working directory for the MS-DOS prompt, which is usually the Favorites folder. A better solution is to use FileSystemObject: |
|
If you save these two lines in a .vbs file and run it, a new directory will be created on the C: drive. This is the starting point for a more interesting utility. Figure 9 shows how simple VBScript code could help you create a folder anywhere. Just define a shortcut, have it point to folder.vbs, and associate it with a hotkey. You can create a new directory without walking all of the Windows submenus. Figure 10 shows it in action (I used Ctrl+Alt+P as the hotkey). |
Figure 10: Creating a new directory |
Registering a New Script Engine
Summary
|