|
Title |
Windows Script Host |
Authors |
Tim Hill |
Publisher |
New Riders |
Published |
Oct 1999 |
ISBN |
1578701392 |
Price |
US 35.00 |
Pages |
448 | |
Chapter 7 - Built-In WSHand VBScript Objects
The previous chapter introduced objects and the object-oriented paradigm. This chapter details some objects that are supplied as part of either VBScript or Windows Script Host, and that are, therefore, available to system script authors.
Objects that are supplied by WSH are available to all system scripts, regardless of the language used. Objects that are supplied by VBScript are only available if the VBScript language is used for scripting. Therefore, if you use another script language, you will not have access to the VBScript objects.
The file system object is also supplied as part of the VBScript. This object is described in Chapter 8, "File System Objects."
Note
As with all the sample scripts in this book, the scripts in this chapter should be run using the CSCRIPT host unless otherwise noted. The examples shown assume that CSCRIPT is the default WSH host. (See Chapter 1, "Introducing WSH," for information on selecting the default WSH host.)
VBScript Objects
VBScript provides the following objects to scripts:
- The
Err
object, which provides access to run-time error information.
- The
RegExp
object, which matches strings against special text patterns, called regular expressions.
- The
Dictionary
object, which provides an item indexing facility.
The Err Object
The Err
object encapsulates errors for a VBScript script. So far in this book, all the sample scripts have used default error handling. By default, if an error occurs, VBScript terminates script execution and WSH reports the error back to the user. Sometimes however, this default error processing is not desirable. In this case, the Err
object and the On Error
statement can be used to let scripts perform their own error handling.
The Err
object is a predefined global object-it does not need to be declared before it can be used. The object is used to encapsulate all the information relating to an error condition. This information is presented as a series of properties, as follows:
- The
.Number
property is the error number (or code) for the error. This is the default property of the Err object.
- The
.Source
property contains a string that specifies the source of the error, typically the ProgID (Programmatic Identifier) of the object that generated the error.
- The
.Description
property contains a string describing the error.
- The
.HelpFile
and .HelpContext
properties store information to reference a help topic in a help file. This allows the error to refer the user to information on possible causes of the error.
To generate a user-defined run-time error, first clear the Err object using the .Clear
method, and then raise the error using the .Raise
method. This method takes up to five arguments that correspond, in order, to the properties previously listed. For example:
Err.Clear
Err.Raise 1000, "This is a script-defined error", "Test Script"
This example displays a message showing the description string followed by a colon and the source string.
To intercept run-time errors and process them in scripts, use the On Error
statement. The syntax of this statement is:
On Error Resume Next
After this statement executes, subsequent run-time errors do not cause script execution to terminate. Instead, the Err
object properties are set to reflect the error information and processing continues with the next statement. For example:
Err.Clear
On Error Resume Next
Err.Raise 100,"Script Error"
If Err.Number Then Wscript.Echo "Error=", Err.Number
In this example, the Err.Raise
method is used to raise a run-time error. Normally, this would terminate script execution. However, the earlier On Error
statement allows script execution to continue, and so the If statement executes and displays the error number.
In the preceding example, the error was generated by the Err.Raise
method. However, the same processing applies to any run-time error, regardless of how it is generated. For example:
On Error Resume Next
Err.Clear
x = CInt("foo")
If Err.Number <> 0 Then Wscript.Echo Err.Number, Err.Description, Err.Source
Here, an attempt is made to convert the string "foo" into an integer. Because this is an invalid conversion, a run-time type mismatch error is generated. The information on this error is placed in the Err object, and this is then processed by the If statement.
After an On Error
statement executes, it remains in effect for the remainder of the procedure in which it executes. If the On Error
statement executes in global scope, it remains in effect until the script terminates. Nested procedures can each have their own On Error
statement. For example, subroutine A can execute an On Error
statement and then execute subroutine B, which in turn, executes an On Error
statement.
If an error occurs while an On Error
statement is active, execution continues with the following statement in the same scope as the most recently executed On Error
statement. For example:
On Error Resume Next
Wscript.Echo "Begin"
Sub1
Wscript.Echo "End"
Sub Sub1
Wscript.Echo "Enter Sub1"
Err.Raise 100
Wscript.Echo "Leave Sub1"
End Sub
In this example, an On Error
statement executes at global scope, and then the Sub1
procedure executes. Within this procedure, an Err.Raise
method is used to generate an error. Because the most recently executed error is at global scope, the next statement to execute is the Wscript.Echo
statement at global scope, and not the Wscript.Echo
statement following the Err.Raise
statement. In fact, the error causes VBScript to abandon further execution of the statements in Sub1
and continue execution at global scope. Thus, the output of this script is:
Begin
Enter Sub1
End
Notice that the final Wscript.Echo
statement in Sub1
never executes. When an error occurs, VBScript immediately abandons execution of whatever running procedures are necessary in order to resume with the correct statement after an error. For example:
On Error Resume Next
Wscript.Echo "Begin"
Sub1
Wscript.Echo "End"
Sub Sub1
Wscript.Echo "Enter Sub1"
Sub2
Wscript.Echo "Leave Sub1"
End Sub
Sub Sub2
Wscript.Echo "Enter Sub2"
Err.Raise 100
Wscript.Echo "Leave Sub2"
End Sub
Here, the Err.Raise
method invocation is nested even more deeply. In this case, when the error occurs, VBScript abandons further execution of both Sub1 and Sub2 in order to continue execution at the global level.
Because VBScript abandons execution of procedures only until it finds the most recently executed On Error
statement, it is possible to capture an error within a procedure simply by placing an On Error statement in that procedure. For example:
On Error Resume Next
Wscript.Echo "Begin"
Sub1
Wscript.Echo "End"
Sub Sub1
Wscript.Echo "Enter Sub1"
On Error Resume Next
Sub2
Wscript.Echo "Leave Sub1"
End Sub
Sub Sub2
Wscript.Echo "Enter Sub2"
Err.Raise 100
Wscript.Echo "Leave Sub2"
End Sub
This example modifies the previous example by adding an On Error
statement to the Sub1
procedure. Thus, when the Err.Raise
method in Sub2
executes, execution continues with the next statement in Sub1
. Notice that the Leave Sub2
line never executes. The output from this example is:
Begin
Enter Sub1
Enter Sub2
Leave Sub1
End
Structured Exception Handling
The O
n Error
statement is a simple form of a technique known as structured exception handling. The basic idea behind this technique is to centralize all the error handling code in a single location outside of the main "flow" of the program. This is the reason for the apparently complex behavior of the On Error
statement.
The assumption is that a large script might contain many procedures that interact in complex ways. It is possible that an error will occur when procedures are nested very deeply. Without the On Error
statement, each procedure must return some form of error code to the procedure from which it was called. In turn, this procedure must do the same thing, and so on for all the nested procedures. This can add greatly to the complexity of the script.
With the On Error
statement, this complexity can be avoided. When an error occurs, VBScript automatically takes care of unwinding out of the complex nest of procedures back to the statement following the original procedure invocation.
The RegExp Object
The InStr
function described in Chapter 3, "VBScript Data Storage," can be used to search a string to see if it contains another string. The RegExp
object provides a far more sophisticated string searching facility by using regular expressions.
A regular expression is a string that describes a match pattern. The match pattern provides a template that can be used to test another string, the search string, for a matching sub-string. In its simplest form, the match pattern string is just a sequence of characters that must be matched. For example, the pattern "fred" matches this exact sequence of characters and only this sequence. More sophisticated regular expressions can match against items such as file names, path names, and Internet URLs. Thus, the RegExp
object is frequently used to validate data for correct form and syntax.
To test a search string against a match pattern, create a RegExp
object and set the match pattern. Then use the .Test
method to test for a match. For example:
Dim oRE, bMatch
Set oRE = New RegExp
oRE.Pattern = "fred"
bMatch = oRE.Test("His name was fred brown")
Regular expression objects are created using the New
keyword, which is described in Chapter 9, "Creating VBScript Classes." This is an anomaly of VBScript, because it is the only object, apart from user-defined objects, that is created in this manner. Once created in this way, the methods and properties of the object are accessed normally.
The .Pattern
property defines the match pattern, and the .Test
method tests the supplied string against this match pattern, returning True if the match pattern is found within the supplied string. In the preceding example, bMatch
is set to True as there is clearly a match.
The .Execute
method of the RegExp
object also checks for a pattern match, but it returns a Matches
collection object that contains detailed information on each pattern match. The Matches
object is a normal collection object containing a .Count
property and a default .Item
property. Each item in the Matches
object is a Match
object that describes a specific pattern match. After the .Execute
method is invoked, the returned Matches
object contains a Match
object for each match located in the search string.
Each Match
item has three properties. The .Value
property contains the actual text in the search string that was matched. The .FirstIndex
property contains the index of the first character of the match in the search string. The .Length
property contains the length of the matched string. Unlike other VBScript string indexes, the .FirstIndex
property uses 0 as the index of the first character in the string. Therefore, always add one to this value before using it with other VBScript string functions.
By default, the .Execute
method only matches the first occurrence of the pattern. If the .Global
property is set to True, the method matches all the occurrences in the string and returns a Match
object for each match. For example:
Dim oRE, oMatches
Set oRE = New RegExp
oRE.Pattern = "two"
oRE.Global = True
Set oMatches = oRE.Execute("two times three equals three times two")
For Each oMatch In oMatches
Wscript.Echo "Match:", oMatch.Value, "At:", oMatch.FirstIndex + 1
Next
This example lists all the matches against the pattern "two" in the specified string.
Simple match patterns, such as those shown in the previous example, provide no additional functionality over that provided by the InStr
function. Much more powerful searches are available, however, by using the special regular expression features of the search pattern. These are most easily explored using the RegExp.vbs sample script shown in Listing 7.1.
Listing 7.1 RegExp.vbs Script
'////////////////////////////////////////////////////////////////////////////
' $Workfile: ShowArgs2.vbs $ $Revision: 5 $ $Date: 4/24/99 11:36a $
' $Archive: /Scripts/ShowArgs2.vbs $
' Copyright (c) 1999 Tim Hill. All Rights Reserved.
'////////////////////////////////////////////////////////////////////////////
' Process a regular expression pattern match
' First arg=regexp match pattern, second arg=search string
Option Explicit
' Check for sufficient command line arguments
Dim sPattern, sSearch
If Wscript.Arguments.Count < 2 Then
Wscript.Echo "usage: regexp <match-pattern> <search-string>"
Wscript.Quit(1)
End If
sPattern = Wscript.Arguments(0)
sSearch = Wscript.Arguments(1)
' Do the regular expression match
Dim oRE, oMatches
Set oRE = New RegExp
oRE.Global = True
oRE.IgnoreCase = True
oRE.Pattern = sPattern
Set oMatches = oRE.Execute(sSearch)
' Now process all the matches (if any)
Dim oMatch
Wscript.Echo "Pattern String: " & Chr(34) & sPattern & Chr(34)
Wscript.Echo "Search String: " & Chr(34) & sSearch & Chr(34) & vbCRLF
Wscript.Echo oMatches.Count, "Matches:"
Wscript.Echo " " & sSearch
For Each oMatch In oMatches
Wscript.Echo " " & String(oMatch.FirstIndex, " ") & String(oMatch.Length, "^")
Next
'////////////////////////////////////////////////////////////////////////////
To use the RegExp.vbs script, execute the script with two command line arguments. Enter a match pattern as the first argument and a search string as the second argument. If either argument contains spaces or special shell characters, enclose the argument in double quotes. The script uses the .Execute
method of the RegExp
object to locate all matches and then displays these matches graphically. Use this script to experiment with the various advanced regular expression features described in the following paragraphs. (Several of the preceding Wscript.Echo
statements use the expression Chr( )
. This simply evaluates to a double quote character.)
Regular Expression Syntax
Within the match pattern, letters, digits, and most punctuation simply match a corresponding character in the search string. A sequence of these characters matches the equivalent sequence in the search string. However, some characters within the match pattern have special meaning. For example, the "." (period) character matches any character except a new-line character. Thus, the match pattern "a.c" matches "abc" or "adc" or "a$c". The match pattern ".." matches any sequence of two characters.
The special character "^" matches the start of the string. Thus, the match pattern "^abc" matches the string "abc", but not "123abc" because this string does not begin with "abc". Similarly, the special character "$" matches the end of the string, and so the pattern "red$" matches the search string "fred", but not "fred brown".
Using both these characters allows a regular expression to match complete strings. For example, the pattern "abc" matches "123 abc that" and any other string containing "abc", whereas the pattern "^abc$" only matches the exact string "abc".
The three characters "*", "+", and "?" are called modifiers. These characters modify the preceding character. The "*" modifier matches the preceding character zero or more times, the "+" modifier matches the preceding character one or more times, and the "?" modifier matches the preceding character zero or one time. For example, the pattern "a+" matches any sequence of one or more "a" characters, whereas the pattern "ab*c" matches "abc", "abbbbbc", and "ac", but not "adc" or "ab".
A list of characters enclosed in brackets is called a range and matches a single character in the search string with any of the characters in brackets. For example, the pattern "[0123456789]" matches any digit character in the search string. Ranges such as this, where the characters are sequential, can be abbreviated as "[0-9]". For example, the pattern "[0-9a-zA-Z_]" matches a digit, letter (either upper or lower case), or the underscore character. If the first character of the range is "^", the range matches all those characters that are not listed. For example, "[^0-9]" matches any non-digit character.
Ranges can be combined with modifiers. For example, the pattern"[0-9]+" matches any sequence of one or more digit characters. The pattern "[a-zA-Z][a-zA-Z_0-9]*" matches a valid VBScript variable name, because it only matches sequences that start with a letter and are followed by zero or more letters, digits, or underscore characters.
To match a character an exact number of times, follow the character in the pattern by a count of matches required enclosed in braces. For example, the pattern "a{3}" matches exactly three "a" characters, and it is equivalent to the pattern "aaa". If a comma follows the count, the character is matched at least that number of times. For example, "a{5,}" matches five or more "a" characters. Finally, use two counts to specify a lower and upper bound. For example, the pattern "a{4,8}" matches between four and eight "a" characters.
As with other modifiers, the pattern count modifier can be combined with ranges. For example, the pattern "[0-9]{4}" matches exactly four digits.
Use parentheses in the match pattern to group individual items together. Modifiers can then be applied to the entire group of items. For example, the pattern "(abc)+" matches any number of repeats of the sequence "abc". The pattern "(a[0-9]c){1,2}" matches strings such as "a0c" and "a4ca5c".
There is a difference between matching the pattern "abc" and the pattern "(abc)+" using the RegExp object. Matching the pattern "abc" against the search string "abcabcabc" generates three individual matches and results in three Match objects in the Matches
collection. Matching the pattern "(abc)+" against the same string generates one match that matches the entire string.
The "I" vertical bar character separates lists of alternate sub-expressions. For example, the pattern "abIac" matches the strings "ab" or "ac". The vertical bar separates entire regular expressions. The pattern "^abIac$" matches either the string "ab" at the start of the search string or the string "ac" at the end of the search string. Use parentheses to specify alternates within a larger pattern. For example, the pattern "^(abIac)$" matches the exact strings "ab" or "ac" only.
To match any of the special characters literally in a pattern, they must be preceded by a back-slash character, which is known as an escape. For example, to match a literal asterisk, use "\*" in the pattern. To match a back-slash itself, use two back-slash characters in the match pattern. The following characters must be escaped when used literally within a match pattern:
. (period) * + ? \ ( ) [ ] { } ^ $
There are also several additional escape sequences that provide useful shorthand for more complex patterns:
- The "\d" escape matches any digit, and it is equivalent to "[0-9]". The "\D" escape matches any non-digit, and it is equivalent to "[^0-9]".
- The "\w" escape matches any word character and is equivalent to"[0-9a-zA-Z_]", and the "\W" escape matches any non-word character.
- The "\b" escape matches a word boundary, which is the boundary between any word character and a non-word character, whereas "\B" matches a non-word boundary.
- The "\s" escape matches any whitespace character, including space, tab, new-line, and so on, whereas the "\S" escape matches any non-whitespace character.
Finally, certain escapes can match non-printing characters, as follows:
- The "\f" escape matches a form-feed character.
- The "\n" escape matches a new-line character.
- The "\r" escape matches a carriage-return character.
- The "\t" escape matches a tab character.
- The "\v" escape matches a vertical tab character.
- The "\onn" escape matches a character whose octal code is nn.
- The "\xnn" escape matches a character whose hexadecimal code is nn.
The special escape "\n", where n
is a digit, matches the search text previously matched by a sub-expression in parentheses. Each sub-expression in a match pattern is numbered from left to right, and the escape "\n" matches the nth sub-expression. For example, the pattern "(..)\1" matches any two character sequence that repeats twice, such as "abab". The first sub-expression matches the first two characters, "ab", and the "\1" escape then matches these same two characters again.
Regular Expression Examples
Regular expression match patterns provide a powerful way to validate the syntax of strings. For example, a script can obtain a command line argument that is the name of a file to create. Before creating the file, a script might want to validate that the command line argument is a valid file name. A regular expression can be used for this purpose.
The ParseArgs.vbs script in Chapter 3 processed command line arguments of the form name=value. This script is simplistic in that it simply breaks apart each argument at the "=" sign - no attempt is made to check if the name and value parts are valid. The following regular expression matches these command line arguments:
[^=]+=.*
This match pattern is interpreted as follows: The range "[^=]" matches any character that is not an "=" sign. The "+" modifier following the range means that the pattern matches any set of one or more characters that are not "=" signs. The next "=" sign in the pattern matches a literal "=" sign (that is, the separator between the name and value parts). Finally, the ".*" pattern matches any sequence of zero or more characters.
Parentheses can be used to make the meaning more clear. For example:
([^=]+)=(.*)
This example is identical to the previous example, but the parentheses help make the individual parts of the pattern more understandable.
Typically, the name in the previous example should be restricted to a valid name. We define valid names as a letter followed by zero or more letters, digits, or underscores. This yields a new regular expression as follows:
([a-zA-Z]\w*)=(.*)
Here, the pattern "[a-zA-Z]" matches any single letter. Then the pattern "\w*" matches zero or more letters, digits, or underscores, using the "\w" escape as a shorthand for "[0-9a-zA-Z]".
The previous regular expression does not allow spaces before or after the name. For example, only the first of these strings matches the expression:
account=123456
account = 575888
account = 5544
The following regular expression corrects this by adding optional leading and trailing whitespace around the name:
(\s*)([a-zA-Z]\w*)(\s*)=(.*)
The new addition, "\s*", matches zero or more whitespace characters.
Here is a sample script that uses this expression to validate commandline arguments:
Dim oRE, oMatches, oMatch, sArg
Set oRE = New RegExp
oRE.Global = True
oRE.IgnoreCase = True
oRE.Pattern = "(\s*)([a-zA-Z]\w*)(\s*)=(.*)"
For Each sArg In Wscript.Arguments
Set oMatches = oRE.Execute(sArg)
If oMatches.Count > 0 Then
Wscript.Echo "Valid argument: " & sArg
Else
Wscript.Echo "Invalid argument: " & sArg
End If
Next
As another example, we can define a command line switch to be an argument of the form:
/name[:|=value]
Another way to define a command line switch is an argument that begins with a slash character and ends with a name. The name can be followed by an optional value that is delimited with either a colon or an equal sign character. The following are valid example switches:
/b
/file=c:\myfile.txt
/debug:on
Here is the regular expression that matches a command line switch:
(\s*)/([a-zA-Z]\w*)((=I:)(.*)I)
This complex expression breaks down as follows:
- The "(\s*)/" pattern matches any leading whitespace followed bythe slash character.
- The "([a-zA-Z]\w*)" pattern matches the name, as in the previous example.
- The "(=I:)(.*)" pattern matches either an equal sign or a colon,followed by any sequence of characters.
- The "((=I:)(.*)I)" pattern makes the "(=I:)(.*)" optional, bymatching either this pattern or nothing.
Using the .Replace
Method
Matching patterns against strings allows a script to determine if a string follows a specific syntax, as shown in the previous examples. The RegExp
object can also be used to assist in modifying the search string. This facility is provided by the .Replace
method, which takes two arguments: the search string and a replacement string, and returns a new string in which all matches in the search string are replaced by the replacement string. For example:
Set oRE = New RegExp
oRE.Global = True
oRE.Pattern = "a"
Wscript.Echo oRE.Replace("all a�s are replaced", "X")
In this example, any "a" character in the search string is replaced by an "X" character. The pattern and replacement strings do not need to be the same length. For example:
oRE.Pattern = "\s+"
Wscript.Echo oRE.Replace("compress all whitespace ", " ")
Here, all sequences of whitespace are replaced by a single space character.
Within the replacement string, the special character sequence "$n" is allowed. If present, this sequence is replaced by the text matched by the nth sub-expression in the pattern. For example:
oRE.Pattern = "^\s*(\w+)\s*=\s*(\w+)\s*$"
sSearch = " this = that"
Wscript.Echo oRE.Replace(sSearch, "$1,$2")
This example works as follows:
- The pattern contains both the start of string "^" and end of string "$" characters. This means that the pattern either matches the entire search string or not at all.
- The pattern matches any whitespace and sequence of one or more word characters, more whitespace, an "=" sign, more whitespace, another set of word characters, and finally more whitespace.
- Both the word patterns are in parentheses, marking them as sub-expressions 1 and 2 respectively.
- When the .
Replace
method is invoked, it matches successfully against the entire search string. This means that the replacement string replaces the entire contents of the search string, because this entire string matched the regular expression. Thus, the string returned by .Replace
is simply the replacement string.
- The replacement string is "$1,$2". As noted, the two sub-expressions in the pattern contain the two words matched in the search string, which in this case are "this" and "that". Thus, the replacement string becomes "this,that", and this is the value returned.
The result of this processing is that the RegExp
object has validated the search string against the match pattern and extracted the required elements from the search string. Additional examples of this use of the RegExp
object are found in Chapter 11, "A Script Developer�s Toolkit."
The Dictionary Object
The Dictionary
object is used to hold a set of data values in the form of (key, item) pairs. A dictionary is sometimes called an associative array because it associates a key with an item. The keys behave in a way similar to indices in an array, except that array indices are numeric and keys are arbitrary strings. Each key in a single Dictionary
object must be unique.
The ProgID for a Dictionary
object is "Scripting.Dictionary", and so the following example creates a Dictionary
object:
Dim oDict
Set oDict = CreateObject("Scripting.Dictionary")
Dictionary objects have one property that should be set before any datavalues are stored in the dictionary. There are two modes for the .CompareMode
property which control how individual keys are compared. If the mode is vbBinaryCompare
(the default), upper and lower case letters in keys are considered distinct. If the mode is vbTextCompare, upper and lower case letters in keys are considered identical. This means that a Dictionary
object in binary mode can contain two keys "Key" and "key", whereas these would be considered the same key in text mode.
To add a value to a Dictionary, use the .Add
method. For example:
Dim oDict
Set oDict = CreateObject("Scripting.Dictionary")
oDict.CompareMode = vbBTextCompare
oDict.Add "Pastrami", "Great"
oDict.Add "Roast Beef", "OK on Sunday"
oDict.Add "Salami", "Not so good"
The first argument to the .Add
method is the key value and the second argument is the item value. There is no limit to the number of values that can be added to a dictionary. To remove a value from a dictionary, use the .Remove
method and specify the key to remove. For example:
oDict.Remove "Salami"
To remove all values and clear the dictionary, use the .RemoveAll
method. Use the .Count
property to obtain a count of values in the dictionary.
The .Exists
method returns True if the specified key exists within the dictionary. For example:
If oDict.Exists("Pastrami") Then Wscript.Echo "Pastrami is available today."
To retrieve the item value for a given key, use the .Item
property. This is the default property for a Dictionary
object. For example:
If oDict.Exists("Salami") Then Wscript.Echo oDict("Salami")
Here, the Wscript.Echo
statement displays the item value stored in the dictionary for the "Salami" key.
Use the .Key
property to change the key value for a given key. For example:
oDict.Key("Salami") = "Italian Salami"
The .Keys
and .Items
methods return an array containing all the keys or items from the dictionary. For example:
aMeats = oDict.Keys
aComments = oDict.Items
Dictionaries are frequently used when some items need to be stored and recovered by name. For example, a dictionary can hold all the environment variables defined by the system or all the values associated with a registry key. However, a dictionary can only store one item for each key value. That is, dictionary keys must all be unique.
WSH Objects
Windows Script Host provides the following objects to scripts:
- The
Wscript
object, which provides access to core WSH operations.
- The
WshArguments
object, which provides access to command line arguments.
- The
WshNetwork
object, which provides access to network shares and information.
- The
WshShell
object, which provides access to miscellaneous system functions.
- The
WshEnvironment
object, which provides access to the system environment variables.
- The WshShortcut and
WshUrlShortcut
objects, which provide access to file system shortcuts.
The Wscript Object
The Wscript
object provides access to core WSH information. This object is predefined by WSH for all scripts and does not need to be declared or created. The methods of the Wscript
object have already been covered elsewhere. The .CreateObject
and .GetObject
methods were described in Chapter 6, "Introducing Objects," and the .Echo
and .Quit
methods were described in Chapter 2, "VBScript Language Essentials," as special "statements," although it should now be clear that these are actually object methods.
In addition to these methods, the Wscript
object also has a number of properties:
- The .
FullName
property contains the full pathname of the WSHexecutable used to run the script.
- The
.Name
property contains the friendly name (title) of the WSHexecutable used to run the script.
- The
.Path
property contains the path (that is, folder name) of theWSH executable.
- The
.ScriptFullName
property contains full path to the script file.
- The
.ScriptName
property contains the full name of the script file, without the path.
- The
.Version
property contains the version of WSH as a string. Note that this is not the same as the version of VBScript that is recovered using the ScriptEngineMajorVersion
and ScriptEngineMinorVersion
functions. These functions return the version of VBScript (the script engine), while the .Version
property returns the version of WSH (the script host). See the Introduction for a discussion of hosts and engines.
The Wscript
object does not provide the folder name where the script file is located. However, this is easily derived from the .ScriptFullName
property. For example:
g_sScriptPath = Wscript.ScriptFullName
g_sScriptName = Wscript.ScriptName
g_sScriptFolder = Left(g_sScriptPath, Len(g_sScriptPath) - Len(g_sScriptName))
The .Sleep
method of the Wscript
object causes script execution to pause for the specified number of milliseconds. For example:
Wscript.Sleep 5000
This pauses the script execution for 5 seconds. While script execution is paused, object events are still processed.
The WshArguments Object
The WshArguments
object encapsulates the command line arguments provided to the script. This object has already been used extensively in examples, such as ShowArgs1.vbs. The Wscript.Arguments
property of the Wscript
object returns this object.
The .Count
property returns a count of command line arguments, whereas the .Item
property returns an individual argument by index. This is the default property for the WshArguments
object.
When WSH parses a command line into arguments, it first removes those arguments that are processed directly by the WSH executable. The arguments all begin with a double slash character and are not passed to the script as part of the WshArguments
object. Remaining arguments are then passed to the script via this object. Individual command line arguments are separated by one or more spaces. To include a space within an argument, enclose the argument in double quotes. The double quotes are not themselves included in the argument text returned by the WshArguments
object.
The WshNetwork Object
The WshNetwork
object provides methods to manipulate network printers and drive management. The ProgID for the object is "Wscript.Network", and so the following example creates a WshNetwork
object:
Dim oNet
Set oNet = CreateObject("Wscript.Network")
The WshNetwork
object supports the following properties:
- The
.ComputerName
property returns the NetBIOS name of the computer.
- The
.UserDomain
property returns the domain name to which the user belongs.
- The
.UserName
property returns the name of the currently logged on user.
For example:
Dim oNet
Set oNet = CreateObject("Wscript.Network")
Wscript.Echo "User: " & oNet.UserDomain & "\" & oNet.UserName
The WshNetwork
object can manage connections to remote computer shared directories. Use the .MapNetworkDrive
method to map a network drive to a local drive letter. The first argument specifies the drive letter; the second argument specifies the UNC name of the network share to map. For example:
oNet.MapNetworkDrive "S:", "\\SERVER1\Setup"
oNet.MapNetworkDrive "L:", "\\SERVER1\Library"
The .MapNetworkDrive
method supports up to three additional, optional, arguments. The first of these is specified if the drive mapping should be made persistent. The default value is False. If this argument is True, the drive mapping is recorded in the registry and restored the next time this user logs on. The final two arguments can specify an alternative user account and password to use when connecting to the specified share. For example:
oNet.MapNetworkDrive "P:", "\\Server2\BobConner", False, "MYDOMAIN\BConner", "secret"
This example maps a non-persistent share to local drive P:
, using the specified domain account and password.
The .RemoveNetworkDrive
method removes a network drive mapping. Specify the drive letter of the drive to remove. For example:
oNet.RemoveNetworkDrive "S:"
This method also supports two optional arguments. The first argument, if True, specifies that the drive mapping is removed even if it is currently in use. The default is not to remove the mapping if it is being used. The second argument, if True, specifies that the removal is persistent. That is, if the drive mapping was previously set up to be persistent, the registry data for this is removed.
The .EnumNetworkDrives
method returns a WshCollection
object that contains a list of all the current network drive mappings. Items in the WshCollection
object are paired. The first item in the pair is the local drive letter; the second item is the UNC path. The collection also includes all network share connections made directly to shares without intermediate drive letters. For these connections, the drive letter string is empty. For example, this script substitutes "- -" in its output for drives without drive letters:
Dim oNet, oDrives, ix, sDrive, sUNCPath
Set oNet = CreateObject("Wscript.Network")
Set oDrives = oNet.EnumNetworkDrives
Wscript.Echo oDrives.Count / 2, "Network Connections"
For ix = 0 To oDrives.Count - 2 Step 2
sDrive = oDrives(ix)
sUNCPath = oDrives(ix+1)
If sDrive = "" Then sDrive = "--"
Wscript.Echo "Drive: " & sDrive, "UNC Path: " & sUNCPath
Next
The WshNetwork
object can also manage network printer connections in a similar manner to the way it handles network share connections. The .AddPrinterConnection
method adds a new printer connection. It uses the same arguments as the .MapNetworkDrive
method, except that the first argument maps a printer port name. For example:
<CODE>oNet.AddPrinterConnection "LPT1:", "\\PrintServer\HPLaser1"
The .AddPrinterConnection
method also supports the same three optional arguments of the .MapNetworkDrive
method.
The .RemovePrinterConnection
method removes a network printer connection. It supports the same arguments as the .RemoveNetworkDrive
method. The .SetDefaultPrinter
method chooses a default printer. The printer name can be either a local printer name (such as "LPT1:") or a share name (such as "\\Server\HP100").
The .EnumPrinterConnections
method enumerates printer connections in a manner similar to the .EnumNetworkDrives
method. It returns a WshCollection
object containing pairs of strings that specify the local printer name and the printer share name. For example:
Dim oNet, oPrinters, ix, sPrinter, sUNCPath
Set oNet = CreateObject("Wscript.Network")
Set oPrinters = oNet.EnumPrinterConnections
Wscript.Echo oPrinters.Count / 2, "Network Connections"
For ix = 0 To oPrinters.Count - 2 Step 2
sPrinter = oPrinters(ix)
sUNCPath = oPrinters(ix+1)
If sPrinter = "" Then sPrinter = "--"
Wscript.Echo "Printer: " & sPrinter, "UNC Path: " & sUNCPath
Next
Note
The printer connections managed by the WshNetwork
object are identical to those managed by the NET USE
shell command. Windows NT and Windows 2000 computers do not always use printers mapped to local devices in this manner, and so not all active printers appear as printer connections.
The WshShell Object
The WshShell
object provides access to a number of system level facilities, including the registry, system environment variables, special folders, and shortcuts. The ProgID
of the WshShell
object is "Wscript.Shell".
The .SpecialFolders
property provides access to the various folders in the Windows environment that have special significance to the shell. These folders should never be accessed directly by name, because the name varies from locale to locale and the user might alter the name. Instead, use the .SpecialFolders
property to access the folder information indirectly. This property returns a collection object that contains the names of all the special folders. These are then accessed indirectly by specifying the type of folder required. For example:
Dim oShell, oSpecialFolders
Set oShell = CreateObject("Wscript.Shell")
Set oSpecialFolders = oShell.SpecialFolders
Wscript.Echo "Your documents are stored in: " & oSpecialFolders("MyDocuments")
Table 7.1 lists the individual special folders that can be accessed via this collection.
Table 7.1 Special Folders
Folder Name Meaning
"AllUsersStartMenu" |
Folder where items in Start menu for all users are stored |
"AllUsersDesktop" |
Folder where items visible on all users desktops are stored |
"AllUsersPrograms" |
Folder where items in Start Programs menu for all users are stored |
"AllUsersStartup" |
Folder where items in Start Programs Startup menu for all users are stored |
"Desktop" |
Folder for this user�s desktop items |
"Favorites" |
Folder for this user�s Internet favorites |
"Fonts" |
Folder where fonts are stored |
"MyDocuments" |
Default folder where user storesdocuments |
"Programs" |
Folder where items in Start Programs menu for this user are stored |
"Recent" |
Folder where shortcuts to recently open documents for this user are stored |
"StartMenu" |
Folder where items in Start menu for this user are stored |
"Startup" |
Folder where items in Start Programs Startup menu for this user are stored |
The .Run
method of the WshShell
object allows a script to execute any other application or command line. The method takes at least one argument, which specifies the command line to execute, including any command line arguments. For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
oShell.Run("notepad")
This example starts a copy of Windows Notepad. The .Run
command accepts any command that can be typed at the Windows command shell prompt.
The .Run
method accepts two optional arguments. The first argument specifies how any applications started by the .Run
method should appear on the desktop, as follows:
- A value of 0 starts the application hidden. The user does not see the application on the desktop.
- A value of 1 (the default) starts the application in a normal window.
- A value of 2 starts the application minimized.
- A value of 3 starts the application maximized.
- A value of 10 starts the application in the same state as the script itself. For example, if the script is minimized, the application is also minimized.
The final argument to the .Run
method determines if the script waits for the command to complete execution. If this argument is False (the default), the script continues executing immediately and does not wait for the command to complete. In this case, the .Run
method always returns 0. If the argument is True, the script pauses execution until the command completes, and the return value from the .Run
method is the exit code from the application. For example:
Dim oShell, nError
Set oShell = CreateObject("Wscript.Shell")
nError = oShell.Run("net start spooler", 1, True)
If nError = 0 Then Wscript.Echo "Spooler service started."
Registry Access Using the WshShell Object
The WshShell
object provides three methods that provide basic access to the system registry:
- The
.RegDelete
method deletes a registry key or value.
- The
.RegRead
method reads a registry value.
- The
.RegWrite
method writes a registry value.
Note
Modifying the registry, though sometimes necessary, should be done with caution. Inadvertent changes to the registry may result in system instability or the inability to boot the operating system correctly. Always debug and validate scripts that modify the registry on test systems that do not contain live data and can be recovered in the event of catastrophe.
All the methods access the items in the registry by key name or value name. The name must begin with one of the predefined key names:
HKEY_CURRENT_USER
or HKCU
to access the per-user information for the current user
HKEY_LOCAL_MACHINE
or HKLM
to access the per-machine information
HKEY_CLASSES_ROOT
or HKCR
to access the per-machine class information
HKEY_USERS
to access other users and the default user
HKEY_CURRENT_CONFIG
to access configuration data
Following the predefined key name are one or more key names separated by back-slash characters. A name that ends with a back-slash is assumed to specify a key name, otherwise the name is assumed to specify a value name.
Use the .RegDelete
method to delete a key or value from the registry. Specify the name of the item to delete. For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
oShell.RegDelete "HKCU\Software\AcmeCorp\WindowSize"
oShell.RegDelete "HKCU\Software\AcmeCorp\"
Here, a registry value and then a key are deleted. The .RegDelete
method cannot delete a key if it contains any subkeys, although it will delete a key that contains one or more values.
The .RegRead
method reads a value from the registry. If the name specifies a key, the default value for that key is read, otherwise the specified value is read from the specified key. For example:
Wscript.Echo oShell.RegRead _
"HKLM\CurrentControlSet\Control\ComputerName\ComputerName\ComputerName"
The .RegWrite
method writes a value into the registry. If the name specifies a key, the default value for that key is written. Otherwise, the specified value is written. For example:
oShell.RegWrite "HKCU\Software\AcmeCorp\LastRunDate", Date
The .RegWrite
method supports one optional argument that specifies the type of data to write to the registry. If can be one of:
- "REG_SZ" or "REG_EXPAND_SZ" to write a string value.
- "REG_DWORD" to write a 32-bit integer value.
- "REG_BINARY" to write a 32-bit binary value.
Application Control Using the WshShell Object
The WshShell
object provides access to two methods that can be used to control Windows applications. These methods are used only with applications that are not COM based. COM applications and objects are manipulated using the object techniques described in Chapter 6.
For older legacy applications, the WshShell
object provides two methods, .AppActivate
and .SendKeys
, that can be used to control the application.
The .AppActivate
method is used to activate a running application and switch the input "focus" to that application. This method does not run an application; it only switches the focus to the application. To run an application, use the .Run
method.
To activate an application, specify its window title (the text displayed at the top of the window) as a single argument. For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
oShell.AppActivate "Calculator"
Here, the application, named Calculator (the Windows calculator applet), is activated.
The .AppActivate
method first tries to find a window with title text that exactly matches that supplied as an argument. If no match is found, the method looks for a window whose title begins with the text specified. Finally, if there is still no match, the method looks for a window whose title ends with the text specified. This allows .AppActivate
to work with applications that add the document name to the window title text.
The second method provided to control legacy applications, .SendKeys
, is used to send keystrokes to the application that currently has the focus. Thus, before using .SendKeys
, the .AppActivate
method is typically used to ensure that the correct application receives the keystrokes specified.
The .SendKeys
method sends keystrokes to the application as if they had been typed at the system keyboard. Thus, by sending the correct sequence of keystrokes, the application can be driven by a script as if it were being used interactively.
To use .SendKeys
, specify a sequence of keystrokes as a string argument. For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
oShell.AppActivate "Calculator"
oShell.SendKeys "1000"
Here, the calculator program is sent the value 1000.
Certain characters in the string argument to the .SendKeys
method have special meanings. These are shown in Table 7.2.
Table 7.2 Special Characters in .SendKeys String
Characters Meaning
{BS} |
Sends Backspace key. |
{BREAK} |
Sends Break key. |
{CAPSLOCK} |
Sends Caps Lock key. |
{DEL} |
Sends Delete key. |
{DOWN} |
Sends down-arrow key. |
{END} |
Sends End key. |
{Enter} or ~ |
Sends Enter key. |
{ESC} |
Sends Esc key. |
{HELP} |
Sends Help (F1) key. |
{HOME} |
Sends Home key. |
{INS} |
Sends Insert key. |
{LEFT} |
Sends left-arrow key. |
{NUMLOCK} |
Sends Num Lock key. |
{PGDN} |
Sends Page Down key. |
{PGUP} |
Sends Page Up key. |
{RIGHT} |
Sends right-arrow key. |
{SCROLLLOCK} |
Sends Scroll Lock key. |
{TAB} |
Sends Tab key. |
{UP} |
Sends up-arrow key. |
{Fn} |
Sends Fn key (for example, {F1} sends F1, {F10} sends F10, and so on). |
{+} |
Sends + key. |
{^} |
Sends ^ key. |
{%} |
Sends % key. |
{~} |
Sends ~ key. |
{(} |
Sends open parenthesis key. |
{)} |
Sends close parenthesis key. |
{{} |
Sends open brace key. |
{}} |
Sends close brace key. |
+key |
Sends key with the Shift key down. |
^key |
Sends key with the Ctrl key down. |
%key |
Sends key with the Alt key down. |
{keycount} |
Sends key exactly count times. |
In the .SendKeys
string, characters with special meanings, such as "+" or "~", must be enclosed in braces if they are to be sent literally. Otherwise, as shown in Table 7.2, they are used to modify the way characters are sent. For example, the string "^S" sends a single Ctrl+S keystroke to the application, whereas the string "{^}S" sends a carat character followed by an upper case S.
The "+", "^", and "%" characters can be used in combination. For example, the string "+^A" sends the Shift+Ctrl+A keystroke to the application.
To send a sequence of keys with a modifier key (Ctrl etc.) held down, enclose the keys in parentheses. For example, the string "+(ABC)" sends the three keys "A", "B", and "C" with the Shift key down.
To specify a repeated keystroke, specify the key and repeat count in braces. For example, the string "{X 10}" sends 10 "X" keys to the application.
Adding Events to the Event Log
The WshShell
object provides a method, .LogEvent
, to add an event to the system event log. On Windows NT and Windows 2000, this method adds an event to the application event log. On Windows 9x, this method adds the event to a file named WSH.log in the Windows directory.
The .LogEvent
method takes three arguments. The first argument specifies the event type. Event types are shown in Table 7.3.
Table 7.3 Event Types
Code Meaning
0 |
Success event. Indicates that an action was successful. |
1 |
Error event. Indicates an error. |
2 |
Warning event. Indicates a condition that should be corrected but was not fatal. |
4 |
Information event. Provides general information. |
8 |
Audit Success. An auditing event that succeeded. |
16 |
Audit Failure. An auditing event that failed. |
The second argument to the .LogEvent
method specifies an arbitrary text string to be logged. This typically contains an informative message describing the event being logged.
The final argument, which is optional on Windows NT and Windows 2000 and ignored on Windows 9x, specifies the name of the computer where the event is to be logged. The default, if not specified, is to log the event on the local computer.
For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
oShell.LogEvent 1, "Script processing failed."
The WshEnvironment Object
The WshShell
provides two ways to access the system environment strings. The .ExpandEnvironmentStrings
method processes a string and replaces any references to environment variables with the values of those variables. Environment variables are enclosed in "%" signs as usual for command shell processing. For example:
Dim oShell
Set oShell = CreateObject("Wscript.Shell")
Wscript.Echo oShell.ExpandEnvironmentStrings("The temp dir is %TEMP%")
The .Environment property of the WshShell
object returns a WshEnvironment
object that can then access individual environment variables. The object returned can access environment variables in one of four sets by specifying a string argument as follows:
- "System" System environment variables that are stored in the
HKEY_LOCAL_MACHINE
portion of the registry.
- "User" User environment variables that are stored in the
HKEY_CURRENT_USER
portion of the registry.
- "Volatile" Volatile environment variables that are constructed on the fly during the system boot and logon process.
- "Process" Process environment variables. These include all the system, user, and volatile variables, and it also includes any variables created by the current process or the process that started the current script.
The "Process" set is typically used when reading variables. To make a change to a variable persistent, use either the "System" or the "User" sets.
Once the WshEnvironment
object has been obtained, variables can be manipulated individually. The WshEnvironment
is a collection object. For example:
Dim oShell, oEnv
Set oShell = CreateObject("Wscript.Shell")
Set oEnv = oShell.Environment("Process")
For Each sItem In oEnv
Wscript.Echo sItem
Next
To change the value of an environment variable or add a new variable, specify the name of the item to change or add and assign it a value. For example:
oEnv("Path") = oEnv("Path") & ";c:\myapp"
This example adds an additional path name to the end of the PATH environment variable.
The .Remove
method deletes an environment variable. For example:
oEnv.Remove "TempDir"
Note that changes to the process set of environment variables are local to the script process and any processes the script creates using the WshShell.Run
method. They are not visible to other processes in the system.
The WshShortcut and WshUrlShortcut Objects
The WshShell
object provides access to two distinct types of shortcuts: the file shortcut and the URL shortcut. Both are stored in small files. File shortcuts provide a link to a file in another location, whereas URL shortcuts provide a link to a Web site or Internet resource.
To create a shortcut, use the .CreateShortcut
method. Specify the full pathname of the shortcut file to be created. This filename must end with a file type of either .LNK
for regular file shortcuts or .URL for Internet URL shortcuts. For example:
Dim oShell, oSC, oURL
Set oShell = CreateObject("Wscript.Shell")
Set oSC = oShell.CreateShortcut("c:\MyDocs.LNK")
Set oURL = oShell.CreateShortcut("c:\MySite.URL")
After the shortcut object is created, set the properties of the shortcut and then use the .Save
method to save the information in the shortcut file.
Regular file shortcuts support the following properties:
.Arguments
Use this property to set additional arguments that are passed to the target application when the shortcut executes.
.Description
Use this property to add descriptive text to the shortcut.
.IconLocation
Use this property to specify the location of an icon for the shortcut. Specify a string containing a path name and icon index. If no icon is specified, the icon appropriate for the shortcut target is used.
.TargetPath
Use this property to specify the full pathname of the target application or document. Always specify a full path name, including a drive letter or UNC name.
.WorkingDirectory
Use this property to specify the directory to be used as the working directory when the shortcut executes. The default is the current working directory.
.WindowStyle
Use this property to specify the initial window location when the application starts. See the discussion of the WshShell.Run
method earlier in this chapter for more information on window styles.
Internet URL shortcuts support the following properties:
.TargetPath
Use this property to specify the full URL to the internet location.
For example:
Dim oShell, oSC, oURL
Set oShell = CreateObject("Wscript.Shell")
oSC = oShell.CreateShortcut("c:\MyDocs.LNK")
oURL = oShell.CreateShortcut("c:\MySite.URL")
oSC.TargetPath = "e:\Users\Me\MyDocs"
oURL.TargetPath = "http://www.macmillantech.com"
oSC.Save
oURL.Save
Summary
The VBScript Err
, RegExp
, and Dictionary
objects provide additional features to assist in the development of scripts. The RegExp
object is particularly suitable for decoding and validating textual information. Dictionaries are useful when items of information must be stored and indexed by a text key.
The Wscript
object provides access to various types of script-level information, such as the name of the script currently executing. The object also provides access to the WshArguments
object, which encapsulates the script command-line arguments.
The WshNetwork
object provides access to logon account information as well as to file and printer shares. The WshShell
object provides access to several other internal objects, including objects to manipulate the system environment strings and system shortcuts. It also provides access to the system registry and various special folders.
Copyright � 2000 New Riders Publishing