Windows Scripting Host (WSH) fills a long-standing gap for batch file processing that has existed since Microsoft first released Windows 3.1. In the past, if you wanted to automate Windows applications, you had to use batch files with the command processor or use the Macro Recorder. Both methods have disadvantages. Batch files are character-based and not well integrated into the graphical environment. The Macro Recorder lacks advanced program flow control and is notorious for sending keystrokes and mouse clicks to the wrong windows if the slightest unexpected variation changes the desktop's or the application's focus.
Fortunately, WSH now provides the native Win32-based scripting that was lacking. WSH lets you write scripts that automate common tasks, perform logons, read and write to the Registry, and launch and control Windows applications.
In this article, I'll first introduce you to WSH and to the WSH object model. I'll then show you two examples of how to use WSH to query and display your system's network values. Finally, I'll show you how to use WSH's support for component object model (COM) to run and control Microsoft Excel.
Welcome to the World of WSH
Microsoft includes WSH with Windows 98 and Internet Explorer (IE) 3.0 and higher. Microsoft will also include WSH with Windows 2000 (Win2K—formerly Windows NT 5.0). You can download the most recent WSH scripting engine from http://www.microsoft.com/msdownload/vbscript/scripting.asp. Although Microsoft supplies the WSH scripting engine, the company doesn't provide a development environment or source editor. However, you can create WSH scripts using any standard text editor, such as Microsoft Notepad.
WSH lets you run either Visual Basic Script (VBScript) or JScript source files. Running WSH scripts is simple. You just double-click a file that has an extension of .vbs (for VBScript) or .js (for JScript). WSH automatically runs wscript.exe, the Windows version of the WSH scripting engine, using the source code from the selected file. You can also run the command-line version of WSH by executing cscript.exe from the command line or by including the cscript.exe line in a batch file. The cscript.exe version lets you use the /B parameter to turn off error messages and prompts.
When running wscript.exe or cscript.exe, you must include the name of the source file that you want to execute (e.g., myscript.vbs) as the first parameter. For example, for wscript.exe, type
For cscript.exe, type
WSH executes VBScript and JScript files interactively, so it doesn't support compiling the scripts into stand-alone executable programs. However, both VBScript and JScript are full-featured programming languages with functionality that far exceeds that of batch files or recorded macros. Both scripting languages can declare variables, provide program flow using If...Then...Else and Do...Loop statements, and perform conditional logic using select statements. The languages also provide a variety of mathematical functions, from addition and multiplication to square root, sine, cosine, and exponentiation. The built-in WSH scripting objects provide support for graphical I/O, file system calls, and Registry access.
The WSH Object Model
Before you start writing WSH scripts, you need to be familiar with the WSH object model. The three main objects are WScript, WshShell, and WshNetwork. The descriptions that follow provide only basic information about these objects. For detailed information, you can download the "Windows Script Host Programmer's Reference." Go to http://msdn.microsoft.com/scripting, select Windows Scripting Host in the navigational menu on the left, click Documentation in the window that appears, and click Technical Paper.
WScript is the primary object in the WSH object model. This object has five methods (CreateObject, DisconnectObject, Echo, GetObject, and Quit) and eight properties (Application, Arguments, FullName, Name, Path, ScriptFullName, ScriptName, and Version). WScript's main method is CreateObject, which lets you create other COM objects. The Echo method is also important, because you can use it to send output to a window. One of the most useful properties is Arguments, because it lets you work with parameters originating from the command line.
WshShell has seven methods (CreateShortcut, ExpandEnvironmentStrings, Popup, RegDelete, RegRead, RegWrite, and Run) and two properties (Environment and SpecialFolders). With WshShell's Run method, you can launch other Windows applications. The object's RegDelete, RegRead, and RegWrite methods let your script read and write to the Registry.
WshNetwork's seven methods (AddPrinterConnection, EnumNetworkDrives, EnumPrinterConnections, MapNetworkDrive, RemoveNetworkDrive, RemovePrinterConnection, and SetDefaultPrinter) provide support for various network objects. For example, you can enumerate network resources and connect or disconnect network drives. With WshNetwork's three properties (ComputerName, UserDomain, and UserName), you can retrieve computer names, users' domain names, and the names of the users who are logged on.
In addition to WScript, WshShell, and WshNetwork, another important object you need to be familiar with is the FileSystemObject, which is part of the Scripting object model. (Both VBScript and JScript follow this model.) FileSystemObject lets your WSH scripts work with OS files and folders. This object has one property (Drives) and 24 methods. Some object methods (e.g., CopyFile, CopyFolder, DeleteFile, DeleteFolder, GetFolder, MoveFile, MoveFolder) let you manipulate files and folders; others let you append a name to an existing path (BuildPath) or open an existing text file (OpenTextFile) so that your script can read and write to the text file. (For a complete list of the FileSystemObject's methods, go to http://premium.microsoft.com/msdn/library/tools/vbscript/htm/vsobjfilesystemm .htm.)
Make a WSH
Now that you've had an overview of the WSH object framework, I'll show you how to make a simple WSH script to display your system's computer name, domain name, and username. Listing 1 contains the example script NetNames.vbs, which uses VBScript to create and manipulate the WshNetwork object. (The NetNames.vbsscript, complete with commentary, and the other scripts discussed in this article are available for download from the Win32 Scripting Journal Web site at http://www.winntmag.com/newsletter/scripting.)
As in standard VB, you begin the script by declaring VBScript variables using a Dim statement. However, implementing VBScript is easier than implementing VB, because you don't need to declare a data type. In this case, the Dim statement declares the variable, oWshNetwork. The prefix o specifies an object. (Another naming convention that you might see for object is the prefix obj.)
Next, use VBScript's Set statement with the WScript's CreateObject method (WScript.CreateObject) to assign an instance of the WshNetwork object to the oWshNetwork variable. When you assign an instance, you're creating a reference between the existing object and the variable you're creating. (To conserve system memory and resources, VBScript creates references to objects rather than making copies of them.) The information in parentheses after WScript.CreateObject specifies the COM class name ("WScript.Network") of the WshNetwork object. You must enclose such class names in quotes.
Now use WScript's Echo method (WScript.Echo) to display a pop-up window that first lists the heading Computer Name: followed by your computer's name, which the script retrieves from WshNetwork's ComputerName property. The carriage-return line-feed character (vbCrLf) tells the script to make a hard return, and the underscore ( _ ) tells the script that the command continues on the next line. On the next line, the window displays the heading Domain Name: followed by your domain's name, which the script retrieves from WshNetwork's UserDomain property. Once again, vbCrLf & _ tells the script to make a hard return and to continue. On the last line, the window displays the heading Logon Name: followed by your username, which the script retrieves from WshNetwork's UserName property. You need to enclose the headings in quotation marks, because they are strings with embedded spaces.
End the script by setting oWshNetwork to Nothing to remove the reference between this variable and the existing object. Removing the reference lets the system reallocate the memory and resources.
As you can see, the WSH and VBScript development environment is similar to that of VB. However, VBScript is easier to use because WSH's built-in objects provide easy access to system information.
Debug Stops Here
You've seen a simple example of WSH in action, so let's take a look at an example that's a bit more complex. The example script ListFiles.vbs in Listing 2 shows how you can launch the WSH script debugger. The example also shows you how to use a collection object to list all the files in a directory and display them in a pop-up window. A collection object is a group or set of related objects. For instance, the Files collection object, which you'll use later, is a group of File objects in which each File object represents an OS file in a folder.
Begin ListFiles.vbs by declaring the script's variables with Dim statements. The prefix s in Dim sFileList specifies that the variable is a string data type. (Another naming convention that you might see for string is the prefix str.) Next, use WScript's CreateObject method to create an instance of the Scripting.FileSystemObject and assign it to the oFileSystemObject variable using VBScript's Set statement.
After creating oFileSystemObject, insert the Stop statement. When you run ListFiles.vbs, the script will stop at this point and launch the WSH script debugger. (For more information about the debugger, see the sidebar "The WSH Script Debugger," page 9.)
Next, create a new Folders object (oFolders) that represents the /temp folder: Use the FileSystemObject's GetFolder method to return a Folder object that corresponds to the folder at the path "c:\temp". Each folder or subdirectory can contain multiple files; the Files collection in oFolders represents the files that the c:\temp folder contains. Use VBScript's For Each...Next statement to loop through the collection of file objects in the oFolder.Files collection. Append sFileList with each file object's name followed by vbCrLf so that each filename is on a separate line. Use WScript's Echo method to display sFileList in a pop-up window. Finally, set oFileSystemObject, oFolder, and oFile to Nothing.
Calling all COMs
With WSH, you can programmatically control any Windows application that supports Object Linking and Embedding (OLE) automation. WSH's ability to execute and control Windows applications with COM objects raises the functionality bar far higher than simple batch files do. Most major Windows applications, including all Microsoft Office applications, expose rich functionality through their respective COM object models. You can then use a COM-enabled development environment such as WSH with VBScript to access that functionality. For example, Listing 3 contains a script, NetDrives.vbs, that launches Excel and uses WSH's COM support to write all the mapped network drives to cells in a worksheet.
I recommend that you begin NetDrives.vbs (or any script that's more than a few lines long) with VBScript's Option Explicit statement. This statement requires that you declare all variables before using them. Like VB, VBScript doesn't require that you declare variables. At first, this feature might seem convenient, but you can introduce subtle bugs in your scripts if you don't declare variables. For example, if you declare a variable named nCount, which you intend to use as a loop counter, but you inadvertently use ncount (no capitalization) in the code, VBScript treats ncount as a separate variable, which can cause unpredictable results. Worse yet, this type of error is often difficult to track down. The Option Explicit statement prevents this type of problem.
After you use the Option Explicit statement, declare the script's working variables and initialize the nCount loop counter to 1. The prefix n in nCount specifies that the variable is numeric. Then, create an instance of the WshNetwork object and assign it to the oWshNetwork variable. Next, use WshNetwork's EnumNetworkDrives method (oWshNetwork.EnumNetworkDrives) to return a collection containing network drive mappings. Assign this collection to the oNetDrives variable.
Now you must manipulate objects from Excel's COM object model. In NetDrives.vbs, you use Excel's top-level Application object and three of its children: the Workbooks collection object, Range object, and Cells collection object. You'll be using the Application object's Visible property, which controls whether users can see an object such as a worksheet or workbook. If you specify True, users can see the object; if you specify False, they can't see it. The Workbooks collection object is a set of Workbook objects, each of which represents a workbook in Excel. The Range object represents a cell, row, or group of cells in a worksheet. The Cells collection object is a set of Cell objects, each of which represents one cell in a worksheet. (For information about these and other Excel objects, check out Chapters 2 and 4 of the Microsoft Office 97/Visual Basic Programmer's Guide at http://www.microsoft.com/officedev/articles/opg/toc/pgtoc.htm.)
To access the Application object, use WScript's CreateObject method to create an instance of the Excel.Application object, assigning it to the oXL variable. Next, set oXL's Visible property to True to display the Excel application to users. Use the Workbooks collection object's Add method to add a new workbook. You don't need to set the return value of the workbook to an object variable because you aren't working with the object's methods or properties. However, if you want to work with the methods or properties, you need to set the return value.
The workbook you just added contains a default worksheet. Each member of the Cells collection object represents a cell in the worksheet. For example, Cells(1, 1) represents cell A1 and Cells(2, 1) represents cell A2. Because you initialized nCount to 1, oXL.Cells(nCount, 1) is Cells(1, 1). You use the Range object's Value property to assign Cells(1, 1) to "Mapped Network Drives".
After setting up the worksheet, use VBScript's For Each...Next statement to iterate through the oNetDrives collection. The nCount counter increments each oNetDrive object (i.e., each network drive mapping) and tells the script which cell to place the drive mapping in. The For Each...Next loop ends when the script reads the last member of the oNetDrives collection. Screen 1 contains example output from this script.
You might have noticed much similarity between the way that you created the Excel.Application object and the way you created the Scripting.FileSystemObject and WScript.Network objects in the previous examples. The reason for this similarity is that COM is the mechanism WSH uses to create and use all of these objects.
If You're WSHing for More
WSH provides the long-overdue scripting engine for the Win32 platform. The WSH scripting object model and VBScript combine to make a powerful ally to take on your Win32 scripting challenges. This article is only an introduction to WSH's wide-ranging capabilities. You can find out more about WSH on Microsoft's Web site at http://msdn.microsoft.com/scripting.