Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Windows Script Host. Chapter 7 - Built-In WSHand VBScript Objects

0.00/5 (No votes)
12 Mar 2001 1  
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.
Sample Image
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 On 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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here