VBScript is a Basic-like language that many popular applications (e.g., Microsoft Outlook, Internet Explorer—IE) and many developer products (e.g., Microsoft Visual Studio—VS) use. VBScript descends from Visual Basic for Applications (VBA), which is the language Visual Basic (VB) and Microsoft Office products rely on. Although Microsoft initially designed VBScript as a scripting language for the Web, VBScript has become a popular language for writing Windows-oriented batch files through the Windows Scripting Host (WSH). With WSH, the Windows OS treats a VBScript file as an executable—in other words, like a batch (.bat) or executable (.exe) file. As a result, you can use VBScript's rich and powerful functions and syntax to compose system-level scripts.
I'll provide you with a global look at VBScript's evolution in the Windows-based scripting scenario. I'll also delve deep into all the aspects of the language. In this first installment, I give you an overview of the system context in which VBScript works and introduce you to the WSH and ActiveX scripting environments. Then, I describe three basic syntax elements: variables, constants, and data types, or simply types.
VBScript is a scripting language that many people consider the modern version of MS-DOS batch files. However, because VBScript inherited VBA's rich syntax and expressivity, VBScript is more akin to a programming language than a simpler scripting language. Unlike programming languages, VBScript doesn't use a compiler, but it still processes code fairly quickly. Overall, VBScript offers the power and design of a programming language while maintaining a scripting language's ease of use.
In the Windows world, you can use VBScript within one of four technologies or environments: WSH, Web-based shell views, Active Server Pages (ASP), and IE. You typically use VBScript code within Web-based shell views, ASP, and IE to produce HTML pages. You typically use VBScript within WSH to automate systems administration tasks. Thus, this series will cover VBScript within WSH only.
WSH is the system module that transforms a VBScript file into a Windows executable file. WSH is readily available for the various Windows OSs. In Windows 2000 (Win2K), WSH is a standard OS component. In Windows 98, WSH is an optional component that you can select during setup. For Windows NT 4.0 and Win95, WSH is available as an add-on.
WSH consists of a Windows-based host (wscript.exe), a console-based host (cscript.exe), the WSH object model (wshom.ocx), the VBScript scripting engine (vbscript.dll), and the JScript scripting engine (jscript.dll). Both wscript.exe and cscript.exe work as a runtime engine that manages and executes VBScript files. The WSH object model is a runtime library of built-in COM objects. The presence of COM is an important aspect of WSH and VBScript. Because VBScript can create an instance of, or instantiate, COM objects, WSH's extensibility has no limits. As a result, you can write scripts that access any system feature and that provide any kind of behavior. The VBScript and JScript scripting engines parse and interpret VBScript and JScript code, respectively.
The underlying technology that enables WSH to run VBScript, JScript, and other language files is ActiveX Scripting. ActiveX Scripting is a COM-based specification that lets Microsoft and third-party vendors provide runtime engines for virtually any scripting language. Any 32-bit Windows application can host an ActiveX Scripting-compliant module and manage and run script files written in various languages. In other words, the ActiveX Scripting interface lets Windows support all types of scripting languages.
For example, WSH and IE are applications that host all ActiveX Scripting-compliant engines and that natively distribute the VBScript and JScript scripting engines. The statement that WSH and IE support only VBScript and JScript means that WSH and IE deploy the parsers for those languages only. (The parser is the runtime module that actually interprets a script file, validating the syntax and processing the instructions. The presence of a runtime parser is what makes a scripting language different from a compiled language such as C++.) Other companies ship ActiveX Scripting engines for Perl, REXX, and Python, and you can use these scripting engines for IE and WSH, too.
VBA has many powerful functions and provides excellent support for variables, data types, and error handling. VBScript inherited much of VBA's functionality, including support for math operations, arrays, flow control, data conversions, COM objects, procedures, and date, time, and string manipulation. However, because Microsoft initially designed VBScript for the Web, Microsoft eliminated direct I/O functions and stripped down the support for types to increase VBScript's processing speed. As a result, VBScript doesn't support explicit types and doesn't include native commands to directly access the client machine's disk.
However, if you use VBScript locally within the WSH environment, you can use two external COM objects to supply the otherwise missing functionality: FileSystemObject, which you use to manipulate files and folders, and WScript, which you use to read and write to the system Registry and more. The scrrun.dll and wshom.ocx files include the FileSystemObject and WScript objects' runtime libraries, respectively. (Scrrun.dll is a system file in VBScript and Win98.)
In the latest version of VBScript, Microsoft has added several new functions and has introduced classes and regular expressions. These additions are moving VBScript closer toward the rank of an effective programming language.
VBScript's syntax includes many elements. Three important elements are variables, constants, and types. A variable is an item that holds data that can change during a script's execution, whereas a constant is an item that holds data that can't change during a script's execution. You classify the data that variables and constants hold into types. For example, long integer numbers are a type called Long, double-precision floating-point values are a type called Double, and text is a type called String.
When you use compiled programming languages, you must explicitly declare the variables you intend to use and specify those variables' types. In VBA and VB scripts, for example, you use the Dim statement with the As qualifier to declare variables and their types:
Dim x As Long
When you use VBScript, you're not required to explicitly declare your variables; if you don't declare your variables, you can't declare their type. However, implicit declaration (declaration that automatically occurs when you use a variable in a script) is a potential source of bugs because typing errors typically go undetected until a problem arises. To prevent such problems, you can add the Option Explicit command at the top of your script. The Option Explicit command forces the runtime engine to accept only those variables you explicitly declare. If you use a variable that you haven't declared, you receive an error message. You can declare variables with any of these commands:
Dim x Dim x,y Private x,y Public x,y,z
You must use the Public and Private commands at the beginning of a script; you can use Dim statements at any point. Variables that you declare at the script's start are script-level declarations that apply to all the subroutines and functions in a script. Variables that you declare within a subroutine or function are procedure-level declarations that apply only to that local subroutine or function.
Notice that the Dim, Private, and Public statements don't include the As qualifier. In VBScript, you can't explicitly declare types. If you use a statement such as Dim y As Long in your VBScript code, you'll receive an Expected end of statement error because the VBScript parser won't understand the additional information that the As qualifier contains. After a Dim, Private, or Public statement, VBScript expects to find a comma followed by another variable declaration, a colon followed by a statement, or a line return specifying the end of the statement.
The lack of a type declaration doesn't mean that VBScript doesn't support types. Rather, VBScript considers all variables the same type: Variant. As Figure 1 shows, the parser manages all the variables through the generic Variant type. If Microsoft had designed VBScript so that you had to explicitly declare types, the parser would've had to perform extensive type checking. Unlike compiled languages, VBScript performs all syntax and type checks during runtime. Thus, VBScript's assumption that all variables are the Variant type saves the parser a great deal of time.
Stating that all variables are the same type might seem implausible, especially when some types are dissimilar, such as Long and String. However, VBScript successfully groups all variables as Variant because Variant is a generic type that provides a uniform programming interface for the other types. In other words, a Variant is a generic reference (i.e., a high-level pointer) to the types. When you specify
you're telling VBScript to create an empty Variant variable. When you specify
x = 45
you're telling VBScript to fill the Variant x variable with the numeric value of 45 and to add information that registers the value's data content as an Integer. This additional information is called the subtype. (People often refer to subtypes as variable types.) You can think of a Variant as a supertype rendered by the
A variable with the Empty subtype differs from a variable with the Null subtype. An Empty variable doesn't contain any data; a Null variable contains no valid data.
Because the Variant type is a high-level reference, you can change a variable's value and subtype fields at runtime by assigning a new value to the variable. For example, Listing 1 changes a variable's content. You begin the code by declaring Dim x and Dim y, which prompts VBScript to create two empty variables called x and y. You then set the x variable to "Hello!" In response, VBScript determines that the "Hello!" value is a String subtype and fills the x variable's value and subtype internal fields with "Hello!" and String, respectively. Similarly, when you set the y variable to 45, VBScript determines that the value of 45 is an Integer subtype and fills the y variable's value and subtype internal fields with 45 and Integer, respectively. Finally, you set the x variable to a new value—the y variable (i.e., 45)—which prompts VBScript to change the x variable's fields from "Hello!" and String to 45 and Integer. As a result, both the x and y variables now have the same value and subtype.
You need to be careful to not set ambiguous values. For example, the value of 1.0 can be a Double, Single, or Currency subtype. By default, VBScript considers 1.0 to be a Double subtype. Even more ambiguous is the value of 1. It can be a Boolean, Integer, Long, or Byte subtype. By default, VBScript considers 1 to be an Integer subtype.
Because the parser declares subtypes for you, you sometimes need to determine the subtype that the parser assigned for a particular variable. VBScript offers many functions that identify subtypes, including the TypeName function, the VarType function, and several IsXxx() functions.
TypeName. You use the TypeName function to identify the subtype name of a specific variable. Listing 3 illustrates how this function works. If you set the x variable to the number 45, TypeName returns a subtype name of Integer. If you set the same x variable to the text "Hello!", TypeName returns a subtype name of String. Finally, if you set the x variable to the date value Now, TypeName returns a subtype name of Date.
Why didn't TypeName return the subtype name of String when you set the x variable to Now? In VBScript, you set text in quotes. If you set the x variable to "Now" instead of Now, TypeName returns a subtype name of String. Without the quotes, Now is a VBScript function that returns the current date and time.
VarType. In Windows, each subtype has an ID number. You use the VarType function to identify a variable's subtype ID number. VarType works similar to TypeName except that VarType returns a number instead of a string. If you need to compare two variables' subtypes or check a subtype against a given value, using VarType is preferable because working with numbers saves you from possible typing errors. Don't dismiss this reason as silly—many seasoned developers and scriptwriters have encountered mysterious bugs only to find out later that mistyped strings were the culprit.
IsXxx(). A series of IsXxx() functions lets you determine whether a specified variable or constant is a certain subtype. To check whether a variable or constant is an Array, Date, Empty, Null, or Object subtype, you use the syntax
in which Xxx is the subtype name and expression is the variable or constant you want to check. For example, if you want to check whether the MyVar variable has the Date subtype, you specify
Like all the Is() functions, IsDate returns the Boolean value. If IsDate returns a value of true, the variable's subtype is Date. If IsDate returns a value of false, the variable's subtype isn't Date.
For numeric subtypes (e.g., Long, Integer, Double), you use the syntax
in which expression is the variable or constant you want to check.
In a programming environment with no explicit types, you might not expect to get a type mismatch error. However, if you try the code in Listing 4, you get the message box in Screen 1. This error occurs because you can't sum numbers and strings, which is what the x + y operation tries to do. When you're using VBScript, you can't forget the elementary rules about types. Although the scripting engine declares, initializes, and passes variables for you, you still need to control advanced subtype operations through conversion functions. VBScript uses an all-encompassing, undistinguished type to achieve better performance by reducing the amount of type-checking. VBScript doesn't use the undistinguished type so that users can freely mix heterogeneous data.
Conversion functions let you convert a value from one subtype to another (e.g., a Long value to a String value) or convert a value from one numeric or alphanumeric system to another (e.g., a hexadecimal value to an octal value). Table 2 describes the conversion functions that you can use. The VarType column displays the ID of the subtype involved.
When you use conversion functions, keep in mind three points. First, you can't pass an alphanumeric string to a conversion function that returns a number (e.g., CInt, CLng). If you try, you'll receive a type mismatch error. (CLng converts a string such as 3 to the Long subtype but not an alphanumeric string such as 3A.) Instead, you can use CInt, CLng, or a similar function to adapt the results of arithmetic operations.
Second, the CStr function provides great flexibility when you're converting an expression to the String subtype. For example, if the expression is a date, you receive a date string that follows your OS's short date format. In the case of a Boolean expression, the string specifies either true or false.
Third, the CDate function effectively converts a string or number to a date. However, you can avoid using a conversion function by assigning the date value to the variable. You just need to enclose the value in hashes (#):
MyDate = "#4/5/99#"
A constant is an explicit value (number, string, or other) to which VBScript or the scriptwriter assigns a name. Constants that VBScript assigns are intrinsic constants. These constants don't change. VBScript defines several categories of intrinsic constants for use in various contexts. For example, the Color category includes intrinsic constants that define various colors (e.g., vbBlack specifies the color black) and the String category includes intrinsic constants that define text-related functions (e.g., vbTab specifies a horizontal tab).
Constants that a scriptwriter assigns can't change during the lifetime of the script. You don't use constants in place of variables. Instead, you use constants in place of explicit values. Using constants is more manageable than using explicit values for two reasons. First, if you need to change a constant's value, you change it only once. Otherwise, you'd need to change that value each time it occurs in the script. Second, constants make scripts easier to read, especially if you assign a mnemonic name to the constant.
To create a constant, you use the syntax
const MyVal = 1234
in which MyVal is the constant name and 1234 is the value of that constant. The value must be explicit. You can't use a function or another constant as the value. For example, the following code isn't valid:
const CRLF = Chr(13) & Chr(10)
After you create the constant, you use the constant name in lieu of specifying that explicit value.
Active Server Pages (ASP) scripting combines HTML with VBScript, JScript or any other ActiveX compliant scripting language. Due in part to the widespread popularity of Visual Basic (VB), VBScript, which is a subset of VB, is probably the most common scripting language used in ASP applications. VBScript shares the syntax and object-naming conventions of its more-capable progenitor. However, ASP pages are more than just listings of ActiveX script. You build ASP pages by combining VBScript and HTML. Inside the pages, you use special script tags to insert VBScript into the HTML. The code in Listing A shows the shorthand form of the tag format that you can use to demark VBScript in ASP pages.
The way ASP scripts generate output is also different from the method that standard VB uses. You can direct output to the user either with the = symbol or by using the Response object’s Write method. The following lines of code illustrate both ways you can direct information out to the browser from an ASP script.
<% = "This writes line one" Response.Write("This writes line two") %>
The code in Listing B creates two simple HTML text boxes that let a Web client enter a user ID and password. Not surprisingly, the name of the user ID field is userid, and the name of the password field is password. After filling out these fields, the Web user clicks Submit to send the form to its form handler. The form handler is a generic technique that you can use in all HTML development environments. If you’re developing in Visual InterDev (VID), you can take advantage of VID’s design-time controls, which let you visually define event handlers for your Web application. In this case, the form handler is an ASP page named loginrsp.asp. The source code for the loginrsp.asp contains the following VBScript:
<% Dim sUser Dim sPwd ' Retrieve form information sUser = Request.Form("userid") sPwd = Request.Form("password") %>
You can use the Request object’s Form method to access the values that users enter into the text boxes on the previous form. The script supplies the name of the HTML inout object to the Form method. To retrieve the value from the object, you must give the Form method the exact name of the object on the original page. In this case, the ASP script retrieves the values for the text boxes named userid and password.
The terms script and scripting language have been widely used (and abused!) to mean just about anything depending on the author and context. For the purpose of this guide I consider scripts to be relatively small text files written and executed without a special development environment, and I consider a scripting language to be the application that interprets and executes a script. Compare that with programs which are compiled from source code (also text files) into processor specific machine object code that is loaded into memory and executed by the operating system.
Or, as Larry Wall (creator of Perl, a popular "scripting language") says, "A script is what you give to the actors. A program is what you give to the audience."
Scripts and scripting languages are well suited to automating repetitive procedures and simplifying file operations, typically in the operating system command shell environment. Windows supports scripting with "DOS" batch files and, commencing with Windows 98, Windows Script Host (WSH). WSH is language independent. VBScript and JScript are included with all Windows distributions after Windows 98 (for Windows 95 you can install WSH, a free download from Microsoft). However, many other languages are supported. For example, if you download and install ActivePerl ( http://aspn.activestate.com/ASPN/Perl), Windows Script Host will execute PerlScript scripts.
The current Windows Script Host version is 5.6
WMI contains several key features that are valuable for solving complex administrative tasks. Those features and capabilities include a Uniform Scripting API, discoverability and navigation, query capability, and powerful event publication and subscription. However, what I find most exciting about WMI is its remote-administration capabilities. Objects that you manage within WMI are, by definition, available to applications and scripts both locally and remotely. No additional work is necessary for managing remote objects.
WMI is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is an industry initiative to develop a standardized technology for accessing management information in an enterprise environment. Management information includes details about the state of system memory, inventories of currently installed client applications, and other information about client status. WMI can handle many tasks, ranging from simple workstation configuration to full-scale enterprise management across multiple platforms. When you implement WMI on Windows platforms, the technology enables the Common Information Model (CIM) designed by the Distributed Management Task Force (DMTF) to represent systems, applications, networks, and other managed components. CIM can model anything in the managed environment regardless of data source location. In addition to data modeling, WMI offers a powerful set of base services that include query-based information retrieval and event notification. One COM programming interface makes possible access to these services and to the management data, which means that you can use WSH scripts to exploit the technology. Microsoft supports the WMI OS core components on Windows 2000, Windows NT 4.0 with Service Pack 4 (SP4) or later, Windows 98, and Win95 OEM Service Release 2 (OSR2).
Both the WMI SDK and the Microsoft Windows 2000 Resource Kit contain a WSH script called exec.vbs. The exec.vbs documentation available at the time of publication explains that you can use exec.vbs to
Very little documentation exists to explain the full functionality of exec.vbs. This lack of documentation is unfortunate because exec.vbs is a powerful script that I know you can put to work immediately to help you automate your job responsibilities.
You can download exec.vbs from the code library on the IIS Administrator Web site (http://www.iisadministrator.com/), or you can extract it from within the WMI SDK on the Microsoft Developer Network (MSDN) Web site (http://msdn.microsoft.com/developer/sdk/wmisdk/). You can place the script wherever you've accumulated your WSH administration scripts, but it can reside in any location.
Although exec.vbs has no documentation, like any good WSH script, its functionality includes brief usage documentation when you execute the script with Help parameters (i.e., /h, /?, or h). Figure 1 shows you how to execute the script with the Help parameter /h. Notice a few points about the usage Help in Figure 1. First, you must specify the username and password that have privileges on the remote machine. Obviously, you can't indiscriminately execute processes on any machine on your network under an Anonymous security context. In addition, if you want to execute processes on machines over the Internet, you need to do some firewall work. WMI's remote process execution operates on port 512, which every firewall blocks by default. Second, you can specify an output filename on the local machine that can capture any screen output and write it to a file for later diagnosis. You use this feature when executing exec.vbs in a scheduled environment (e.g., when the Win2K or NT Task Scheduler executes the script automatically). If you need help identifying a process ID, you can use another WSH script, ps.vbs, which is also available for download from the IIS Administrator Web site.
Let's put those capabilities to work. Consider the following WSH script execution of exec.vbs and its parameters:
cscript exec.vbs /e _"C:\Program Files\ _ Internet Explorer _ \Iexplore.exe" /s _ "TargetServer" /u _ "Administrator" /w _ "Password"
The effect of this command is to run Microsoft Internet Explorer (IE) on a completely different computer called "TargetServer." Note that I've included the absolute path to IE: Execution takes place in the \winnt\system32 folder on the remote machine, and because IE neither resides in that folder nor is mapped to it, an absolute path to IE's location is necessary. The \winnt\system32 folder contains literally hundreds of programs. If you have access to an administrative account on a remote Win2K (or NT 4.0 with SP4 or later) server on your network and you know that that server isn't currently in use (either directly or indirectly), try the following code:
cscript exec.vbs /e sol.exe _ /s TargetServer /u _ Administrator /w _ password