Archived from http://www.mhuffman.com/notes/language/vbs_intro.htm, which is sadly no longer available.


Introduction to VBScript and Windows Script Host


About This Guide

This is a brief introduction to the VBScript language under Windows Script Host (WSH). The target audience is community college students taking their first-year "computer concepts" classes, most of whom have not taken an operating systems class or formal programming language class. My goal is to provide enough introductory background and information so that VBScript can be used as a vehicle for demonstrating broad conceptual topics such as languages in general; differences between low-level and high-level languages; compilers & interpreters; algorithms and basic control structures; and fundamental database concepts. This guide is not intended to be a complete VBScript tutorial, and only presents essential WSH methods and properties to handle input and output (I/O).

[ TOP ]



Windows Script Host (WSH)

The terms script and scripting language have been widely used (and abused!) to mean just about anything depending on the author and context. For the purpose of this guide I consider scripts to be relatively small text files written and executed without a special development environment, and I consider a scripting language to be the application that interprets and executes a script. Compare that with programs which are compiled from source code (also text files) into processor specific machine object code that is loaded into memory and executed by the operating system.

Or, as Larry Wall (creator of Perl, a popular "scripting language") says, "A script is what you give to the actors. A program is what you give to the audience."

Scripts and scripting languages are well suited to automating repetitive procedures and simplifying file operations, typically in the operating system command shell environment. Windows supports scripting with "DOS" batch files and, commencing with Windows 98, Windows Script Host (WSH). WSH is language independent. VBScript and JScript are included with all Windows distributions after Windows 98 (for Windows 95 you can install WSH, a free download from Microsoft). However, many other languages are supported. For example, if you download and install ActivePerl ( http://aspn.activestate.com/ASPN/Perl), Windows Script Host will execute PerlScript scripts.

[ TOP ]



Getting and Installing WSH

Programs (e.g. "scripts") written in a WSH supported language are ASCII text files. All you need to write a WSH program is a text editor such as Windows Notepad (or any of the many Notepad replacements; see Resources > Text Editors). However to run a WSH program you need Windows Script Host installed on your system and an interpreter, also called the scripting engine, for your program. All versions of Windows from Windows 98 onward include the Windows Script Host and "engines" for VBScript and JScript (Microsoft's version of JavaScript). See the Resource > Windows Script Host page for links to download the current version of WSH and documentation from Microsoft.
The current Windows Script Host version is 5.6

To check the version of your Windows Script Host copy the following VBScript script to an ASCII text file and name it version.vbs:

    ' version.vbs
    Wscript.Echo Wscript.Version

Double-click on version.vbs, or from the Command Prompt enter the command cscript version.vbs

Windows Script Host version, GUI output   Windows Script Host version, GUI output
WSH version, GUI   WSH version, Command Line

[ TOP ]



Visual Basic Script Edition (VBScript)

VBScript is derived from Visual Basic, which has origins in GW-Basic that was shipped with all early versions of MS-DOS. GW-Basic evolved from the original Dartmouth BASIC (Beginners All-purpose Symbolic Instruction Code) developed in the 1960's.

VBScript is an interpreted language - sort of. Like many other contemporary "interpreted" languages, Windows Script Host compiles source code (ASCII text files) into an intermediate "byte code" language after scanning for syntax errors, than calls the applicable "scripting engine" to interpret the compiled byte code. Unlike traditional compiled languages, however, the intermediate binary code is not written and saved as a machine readable object file. Each time a WSH program is run the intermediate compile step is repeated. One of the disadvantages of interpreted languages commonly given is the translation time penalty each time the program is run. While this is generally true, WSH is quite fast and efficient. On the other hand a commonly cited advantage of interpreters is their use as quick and (relatively) easy prototyping tools, an area where VBScript's close lineage to Visual Basic and Visual Basic for Applications (VBA) is particularly advantageous.

[ TOP ]



Running a VBScript Program

Windows Script Host is implemented by two different "interpreters" or hosts: cscript.exe and wscript.exe. CScript executes scripts in a Windows "console," or Command Line environment and CScript executes scripts in a GUI environment. Host specific code is minimal, primarily limited to I/O (Input/Output). Unlike other stand alone interpreted and scripting languages, the WSH languages do not have their own I/O functions and operators like print, input, write, read, etc. I/O is handled by WSH objects that can be called by all the supported languages.

The GUI host (WScript) displays its output in text boxes, usually with an OK button that must be clicked to clear the box and resume the program, which quickly becomes an annoyance if the program does much output. All the examples in this guide will use the Console host (CScript) and will be executed from a Windows console (a.k.a. "DOS" window) by explicitly calling cscript.exe followed by the script name, including the .vbs extension.

Example:

' hello.vbs

WScript.Echo "Hello, World!"        ' ubiquitous first program

D:\temp>cscript hello.vbs
Hello, World!

[ TOP ]



Windows Command Prompt

Use either of the following methods to open a Windows Command Prompt session:

Command Prompt Shortcut RUN Command
  • Click on the Command Prompt menu item on the Windows Start Menu or one of its sub-menus.
    • By default a Command Prompt shortcut will be in the Accessories sub-menu tree:
      Start > Programs > Accessories
    • It may also be in the Start menu main opening menu
  • Open a Command Prompt window using the RUN command:  Start > Run
    • Windows 9x, ME
      Type command
    • Windows NT, 2000, XP
      Type cmd
    • Any Windows Operating System
      Type %COMSPEC%
  • Click OK

[ TOP ]



VBScript Statements & Expressions

An expression is a chunk of VBScript syntax in the form of a calculation that uses operators to combine numbers, strings, and variables and evaluate them to some value. An expression can be used any place where a variable is used, pretty much like in mathematics.

A statement is a command telling the computer what to do, not unlike a statement in English: "Turn left on Main Street," "Close the door," etc. In VBScript statements are terminated at the end of a line when you hit the Enter key and your text editor inserts the Carriage Return (ASCII 13) and LineFeed (ASCII 10) characters. If you have a statement that is too long to fit on one line without scrolling off the right edge of the screen you can use the underscore as a line continuation character. For line continuation the underscore must be the very last character on the line without even a space following it, and it must be between keywords, variable names, operators, and quoted strings. Multiple statements separated by a colon can be included in a single line.

The "'" character (single quote) is the comment delimiter. Anything following this character to the end of the line is ignored by VBScript. You can also use the Rem statement for comments. If you use Rem on a line with another statement you must separate the two with a colon (Rem is a statement, not a delimiting operator). Rem is not used very much; most people use the single quote comment delimiter. There is no "multi-line" comment delimiter in VBScript.

Rem     one way to write comments
'       another way to write comments

Cost = 12.5                     ' simple statement assigns 12.5 to cost
Price = cost * 0.2              ' simple statement assigns value of
                                '   the expression cost * 0.2 to price

' separate multiple statements on one line with a colon
Cost = 12.5 : Price = Cost * 0.2        : Rem 3 statements on this line

' break up long statements and use indentation for clarity
TotalCredits = SalesmanOfMonthCredit + _
               UnusedVacationCredit + _
               SeniorDepartmentEmployeeCredit

[ TOP ]



VBScript Data Types, Variables, and Operators

Data Types & Variables <Operators> <Comparison Operators>

Unlike languages that define types and sizes of numbers (integers, floating point, etc.), characters, strings, etc. as distinct data types, VBScript treats all data as one of two fundamental types: numbers or strings. Most of the time VBScript figures out how to make the conversions based on context. When you need explicit control over data types VBScript has conversion functions and data type functions that return the type of variables and expressions.

Variables are used to store data items that can change (e.g. "vary") during the lifetime of a program. All variables have one variable type called variant. The data is actually stored in numbered memory addresses in the computer's Random Access Memory (RAM), however variables in high-level languages like VBScript provide convenient names for the memory addresses. Variables and memory addresses are similar to a house where you deliver the newspaper: it might have a lot number, plot number, section number, and township number for the official county engineer records; but you know it as "123 Main St.," "Mr. Smith's house," or maybe "the big red house on the corner with the mean dog."

Variables in VBScript do not have to be "declared" before they are used, they spring to life when you first use them. This might sound convenient, but it is now generally considered a bad idea, although it persists for historical reasons and backward compatibility with earlier versions of Basic. VBScript supports the Dim statement, however, that allows you to explicitly declare the variables you intend to use. The Option Explicit is also supported, which forces you to use the Dim statement for all variables. When used, Option Explicit must be the first executable statement in the program.

VBScript variable names are not case sensitive. The variables TotalPrice, totalprice, and TOTALPRICE all refer to the same variable. Variable names can be made up of letters, digits, and the underscore character only (no spaces); must begin with a letter; and cannot be the same as VBScript built-in key words (such as For, While, etc.).

If variables are used to store data items that can change then it should follow that constants are used to store data items that cannot change. VBScript supports the Const key word to declare symbolic constants. A common naming convention borrowed from languages like C and Java (which are case sensitive) is to use all upper case for symbolic Constants. Remember, however, that VBScript is not case sensitive.

Const PI = 3.14159265358979     ' the constant Pi
Const MAX_RECORDS = 100         ' size of an array of records
Const ID = 0                    ' array indices for a "structure"
Const FNAME = 1
Const LNAME = 2

An array is a type of variable that can hold a list of single variables that are referenced by their numerical index starting at 0. The index, also called a subscript, is an integer. Because indexing starts at 0 the first element in an array is ArrayElement(0), the second is ArrayElement(1), etc. The index of the last element in an array will always be 1 less than the number of elements in the array and is called the upper bound. The lower bound is always 0. Arrays must be declared with a Dim statement (whether or not Option Explicit is used) indicating the upper bound so that the correct amount of memory can be reserved.

' declare array of 5 elements
' indexing starts at 0, therefore upper bound is 4
Dim score(4)

' initialize array of 5 test scores
score(0) = 93       : score(1) = 88     : score(2) = 100 :
score(3) = 65       : score(4) = 79

' Arrays are indexed lists of variables
' All variables are type variant
' Variables (and thus array elements) can contain other arrays
Dim stuff(5)
stuff(0) = 3.14159  : stuff(1) = "foo"  : stuff(2) = 1024
stuff(3) = "bar"    : stuff(4) = score  : stuff(5) = "WSH Version 5.6"

Wscript.Echo stuff(4)(3)            ' displays 65

VBScript provides 2 built-in functions for working with arrays.
UBound() returns the upper bound of an array. Since the upper bound of an array is always one less than the total elements in the array, we can determine the size.

Wscript.Echo "UBound =", UBound(score)              ' UBound = 4
Wscript.Echo "NumElements =", UBound(score) + 1     ' NumElements = 5
Wscript.Echo "UBound =", UBound(stuff)              ' UBound = 5
Wscript.Echo "NumElements =", UBound(stuff) + 1     ' NumElements = 6

The Array() function constructs a dynamic array from a list of expressions which can be assigned to a variable. This is called an "anonymous array" in some languages because the items in the list are never assigned to elements in a named array. They exist in a temporary unnamed array in memory, and that array is immediately assigned to a variable (typically an element of another array). However, because a reference to the "temporary" list still exists (in the form of array elements in the variable they were assigned to), the memory and its values remain accessible.

Arrays stored in elements of other arrays are the basis for more interesting and useful data structures. In many other languages these are called structures or records. Consider a database of Employee information where each employee has an ID, a first and last name, and number of hours worked.

' employee.vbs

Option Explicit

Const ID    = 0         ' Employee record ID index
Const FNAME = 1         ' Employee record first name index
Const LNAME = 2         ' Employee record last name index
Const HOURS = 3         ' Employee record hours worked index

Dim tblEmployee(100)    ' DB table: array of Employee records

' use Array() function to construct anonymous arrays then store
' them in array of records
tblEmployee(0) = Array(101, "Fred", "Flintstone", 30)
tblEmployee(1) = Array(105, "Barney", "Rubble", 20)

Wscript.Echo "Employee ID:", tblEmployee(0)( ID ), _
             " Last name:", tblEmployee(0)( LNAME ), _
             " Hours:", tblEmployee(0)( HOURS )

Wscript.Echo "Employee ID:", tblEmployee(1)( ID ), _
             " Last name:", tblEmployee(1)( LNAME ), _
             " Hours:", tblEmployee(1)( HOURS )

D:\temp>cscript employee.vbs
Employee ID: 101  Last name: Flintstone  Hours: 30
Employee ID: 105  Last name: Rubble  Hours: 20

[ TOP ]



<Data Types> Operators <Comparison Operators>

VBScript uses many familiar or intuitive operators, such as +, -, *,and / for addition, subtraction, multiplication, and division. VBScript has an additional division operator, \, which performs integer division. 8 / 5 is 1.6, where 8 \ 5 is 1. The exponentiation operator is ^. An operator supported in virtually all programming languages that may be new is the modulus division operator. Modulus division returns the remainder rather than the quotient. In VBScript the modulus operator is MOD.

VBScript has one operator for strings, the "&" (ampersand) operator to concatenate (combine) strings. VBScirpt supports many additional operations for strings implemented by functions. For example, you can extract parts of a string with Mid(); convert strings to upper and lower case with UCase() and LCase; remove leading white space, trailing white space, or both with LTrim(), RTrim(), and Trim(); and convert strings to various data types with CInt() (integer), CDbl() (double precision), CCur() (currency), etc.

Operation           Operator    Example         Result

Addition                +           7 + 2            9
Subtraction             -           7 - 2            5
Multiplication          *           7 * 2            14
Division                /           7 / 2            3.5
Integer division        \           7 \ 2            3
Exponentiation          ^           7 ^ 2            49
Modulus division        MOD         7 MOD 2          1
String concatenation    &           "Foo" & "Bar"    "FooBar"

Some notes regarding VBScript division:

[ TOP ]



<Data Types> <Operators> Comparison Operators

Comparisons are tested with the familiar < and > symbols used in mathematics for "less than" and "greater than". "Less than or equal to" and "greater than or equal to" use the <= and >= operators respectively. Equality is tested with the = operator and inequality ( "not equal to" ) is tested with the <> operator. Note that = is used for both assignment and test for equality; VBScript knows the difference based on context.

Comparison          Operator   Returns

Less than               <          True if a is less than b
Greater than            >          True if a is greater than b
Less than or equal      <=         True if a is not greater than b
Greater than or equal   >=         True if a is not less than b
Equal                   =          True if a is equal to b
Not equal               <>         True if a is not equal to b

Logical operators are used to evaluate logical (e.g. TRUE or FALSE) expressions. In the table below a and b are assumed to represent logical expressions.

Logic               Operator    Returns

AND                     And         True only if a and b are both true
OR                      Or          True if a or b is true, or both are true
Exclusive OR            Xor         True if a or b is true, but not both
Equivalence             Eqv         True if a and b are the same
Implication             Imp         False only if a is true and b is false
                                        otherwise true
NOT                     Not         True if a is false; False if a is true

Logical operators normally combine 2 expressions into one logical value, such as char = "x" Or char = "X" (is the character an 'X', either lower case OR upper case). Every day, non computer examples:

The logical operators can also make logical bitwise evaluations of expressions (beyond the scope of this guide). Logical relationships are commonly written as a Truth Table:

a   b     a And b    a Or b     a Xor b    a Eqv b    a Imp b    Not a

T   T          T          T            F           T           T          F
T   F          F          T            T           F           F          T
F   T          F          T            T           F           T
F   F          F          F            F           T           T

And and Or are the most commonly used in comparisons. Not can be used, but the <> (not equal) operator usually suffices. Xor has interesting and handy uses for bitwise operations. Imp and Eqv are seldom, if ever, used, and many other widely used languages do not have them.

[ TOP ]



VBScript I/O

Output <Input>

So far all examples have displayed output using the Wscript.Echo method which is part of the Wscript object. Do not confuse the wscript.exe command and the WScript host with the Wscript object; they are completely different entities. The Wscript object is available to both hosts. As stated previously, Windows Script Host supports two "hosts:" a GUI host via wscript.exe and a console, or command line host via cscript.exe. Wscript.Echo works with both hosts (see the version.vbs example earlier). Under CScript it simply echoes output to the console window and advances the cursor to the beginning of the next screen line; under WScript it displays a graphical text box which halts script processing until you click the OK button. Unfortunately, there is no equivalent for input (e.g. one single object method supported by both hosts).

Wscript.Echo is rather limited; in the GUI it only provides for an "OK" response from the user, and in the console it always terminates with a new line. However, if you can live with those limitations (and for a lot of "quick and dirty" scripts you can), you know that what ever host executes the script you will get reasonable error free output. Other means of output are

VBScript MsgBox function called from CScript host   Wscript.StdOut.WriteLine called from Wscript host
VBScript MsgBox function called from CScript host   Wscript.StdOut.WriteLine called from Wscript host

[ TOP ]



<Output> Input

The VBScript InputBox() function, as the name suggests, gets input via a graphical input window and, like its MsgBox counterpart, works the same in both hosts. The Wscript.StdIn.ReadLine and Wscript.StdIn.Read methods receive input on the command line in a console window and, like their Wscript.StdOut opposites, only work under the CScript host; scripts executed by WScript will fail with an error similar to the one shown above. There is no "one single method will do something reasonable" under both hosts like the Wscript.Echo method, as handy as it would be.

Here is a dialog between VBScript and a user that prompts the user to enter their name and displays a greeting. This script uses the InputBox and MsgBox functions; and will display the same graphical I/O windows from either host. Use CScript to execute this script with the command cscript input1.vbs from a Command Prompt. Use WScript with the command wscript input1.vbs from a Command Prompt or by double-clicking the file name in Windows Explorer.

' input1.vbs

Option Explicit

Dim name

name = InputBox("Enter your name")
MsgBox ("Hello, " & name & ", welcome to CIS 121!")
VBScript InputBox   VBScript MsgBox
VBScript InputBox   VBScript MsgBox
' input2.vbs

Option Explicit

Dim name

Wscript.StdOut.Write "Enter your name: "        ' prompt user for input
name = Wscript.StdIn.ReadLine                   ' get user's name

Wscript.Echo "Hello, " & name & ", welcome to CIS 121!"
' could also use Wscript.StdOut.WriteLine

D:\temp>cscript input2.vbs
Enter your name: Bullwinkle
Hello, Bullwinkle, welcome to CIS 121!

D:\temp>

Historically, scripting languages have almost exclusively used a command line interface. The main advantage of reading from standard input (StdIn) and writing to standard output (StdOut) is the ability to use redirection and piping and create "filter type" utilities. However, many Windows scripting tasks, such as working with the Registry, do not need input, and perhaps only need to output an error message if something goes wrong. It makes perfect sense to be able to execute these scripts without leaving the GUI.

When you double-click on a VBScript file with a registered extension (only .VBS is discussed here), or enter the script name on the command line without a host, Windows calls the default host to execute the script. The default host under a normal Windows and WSH setup is Wscript, although the default host can be changed with the //H:hostName option.

D:\temp>cscript hello.vbs     && REM hello.vbs executed by CScript

D:\temp>hello     && REM hello.vbs executed by default host, normally WScript

Within a script the Wscript.FullName property reports the full path to the host executing the script. The section on string and text processing shows how to search this string and test for a host, then branch accordingly. You can also query various Registry keys to determine the default host in case you have reason to believe a user has changed it. If you primarily use console scripts it makes sense to set CScript as the default host so that you can just type script_name on the command line rather than cscript script_name.vbs

[ TOP ]



Program Control - Selection (Conditional, Branching)

Conditional statements that allow the default sequential flow of a script to branch to various sections (sometimes called blocks) of code based on input, processing of data, or errors is fundamental to virtually all high-level languages. The simplest VBScript conditional statement is the If ... Then statement:

If condition Then statement     ' single-line conditional statement

If condition Then               ' multi-line conditional statement
    statement                   '   with "block" of statements
    ...
End If

Frequently you have an "either/or" condition where you always want to take some action if the condition is false which calls for the If ... Then ... Else statement:

' single-line If ... Then ... Else
If condition Then true_statement Else false_statement

If condition Then           ' multi-line If ... Then ... Else
    true_statement(s)
    ...
Else
    false_statement(s)
    ...
End If

When there are multiple conditions to evaluate, each with their required action(s), use an extended form that includes ElseIf, using as many additional ElseIf's as necessary to meet all the conditions. The Else block is for the default action, but is not required if the default is simply to continue with the script.

If condition_1 Then         ' multi-branch conditional statement
    statement(s)_1
    ...
ElseIf condition_2 Then
    statement(s)_2
    ...
ElseIf ...                  ' additional ElseIf's as needed
    ...
Else                        ' the default if all else fails
    false_statement(s)
    ...
End If

Note the spelling: ElseIf is one word and "Else" is spelled with an 'e'; End If is two words. Other languages have similar constructs with various combinations of spelling and word spacing.

[ TOP ]



If <If Else> <If ElseIf> <Select Case>
' if.vbs
' Calls StdOut & StdIn methods; execute with cscript.exe

Option Explicit

Dim order, discount

Wscript.StdOut.Write "What is your total order? "
order = Wscript.StdIn.ReadLine                      ' how much did customer spend

' check for first condition
If order < 100 Then discount = order * .1

' check for second condition
If order >= 100 Then discount = order * .15

Wscript.Echo "Your discount is $" & discount        ' display results

D:\temp>cscript if.vbs

What is your total order? 50
Your discount is $5
D:\temp>cscript if.vbs
What is your total order? 120
Your discount is $18

D:\temp>

[ TOP ]



<If> If Else <If ElseIf> <Select Case>

Rather than use two If statements the If . . . Else construct is more descriptive of what we really want to do: if the customer spent less than a given amount give them one discount, otherwise give them a bigger discount:

' ifelse.vbs
' Calls StdOut & StdIn methods; execute with cscript.exe

Option Explicit

Dim order, discount

Wscript.StdOut.Write "What is your total order? "
order = Wscript.StdIn.ReadLine                      ' how much did customer spend

If order < 100 Then
    discount = order * .1
Else                                                ' clearer that we are doing
    discount = order * .15                          '  an "either / or" test
End If

Wscript.Echo "Your discount is $" & discount        ' display results

[ TOP ]



<If> <If Else> If ElseIf <Select Case>

You can also add additional tests with one or more ElseIf statements following If. A final Else following ElseIf is not required, although it is generally good programming practice to have a "default" condition.

' elsif.vbs
' Calls StdOut & StdIn methods; execute with cscript.exe

Option Explicit

Dim order, discount

Wscript.StdOut.Write "What is your total order? "
order = Wscript.StdIn.ReadLine                      ' how much did customer spend

If order < 100 Then                                 ' check for first condition
    discount = order * .1
ElseIf order < 500 Then                             ' check for next condition
    discount = order * .15
Else                                                ' easy to add additional test
    discount = order * .2                           ' big spender gets big discount
End If

Wscript.Echo "Your discount is $" & discount        ' display results

D:\temp>cscript elseif.vbs
What is your total order? 80
Your discount is $8

D:\temp>cscript elseif.vbs
What is your total order? 200
Your discount is $30

D:\temp>cscript elseif.vbs
What is your total order? 600
Your discount is $120

D:\temp>

[ TOP ]



<If> <If Else> <If ElseIf> Select Case

Frequently the multi-way If ... ElseIf construct can be better implemented with a Select Case statement (also called a switch in some languages) that tests if an expression matches one of a number of expressions.

Select Case test_expression
    Case const_expr_1           ' cannot be Boolean expression
        statement(s)_1          ' execute statement(s) up to next Case
        ...
    Case const_expr_2
        statement(s)_2
        ...
    Case Else                   ' default if no matches (optional)
        statement(s)
        ...
End Select

The Case expressions must evaluate to constant values (e.g. an integer, string, etc.); you cannot use Boolean expressions. In other words, the discount example above cannot be implemented as a Select Case statement.

If the test expression matches any Case constant expression the statements following that Case will be executed up to the next Case. Statements following the (optional) Case Else are the default statements to be executed if no expressions match the test expression.

The following example introduces a loop which will be discussed in the next section.

' select.vbs
' Calls StdOut & StdIn methods; execute with cscript.exe

Option Explicit

Dim flag, flag_colors
flag_colors = "(green, yellow, checkered) "

Do
    Wscript.StdOut.Write "What flag? " & flag_colors
    flag = Wscript.StdIn.ReadLine

    Select Case flag
        Case "green"
            Wscript.Echo "Race on!"
        Case "yellow"
            Wscript.Echo "Caution: no passing"
        Case "checkered"
            Wscript.Echo "You won the race!"
        Case Else
            Wscript.Echo "  *** Please enter another flag"
    End Select
Loop Until flag = "checkered"

D:\temp>cscript select.vbs
What flag? (green, yellow, checkered) yellow
Caution: no passing
What flag? (green, yellow, checkered) green
Race on!
What flag? (green, yellow, checkered) red
  *** Please enter another flag
What flag? (green, yellow, checkered) checkered
You won the race!

D:\temp>

[ TOP ]



Program Control - Iteration (Repetition, Loops)

Do While/Until <For> <For Each>

The fundamental construct to iterate, or repeat a block of code more than once, is the Do While loop. Technically all loops can be written using Do While. However, additional looping structures are useful in a high-level language to allow programmers to express logic in language syntax similar to how it would be spoken in English. Pseudo Code can frequently be translated to VBScript code with very few changes.

Do While condition
    statement(s)
    ...
Loop

The Do While tests a condition at the beginning of the loop, executes the body of the loop if the test passes the specified condition, then goes back to the top and tests the condition again. As long as the test passes the condition the body of the loop continues to be executed.

' while.vbs
' Calls StdOut & StdIn methods; execute with cscript.exe

Option Explicit

Dim i

Wscript.Echo "Calculate powers of 2"
Wscript.Echo                                ' blank line for spacing

i = 0
Do While i < 8
    Wscript.StdOut.Write 2^i & Chr(9)       ' ASCII 9 is the TAB character
    i = i + 1                               ' be sure to include logic that
Loop                                        '  will terminate the loop
Wscript.Echo                                ' send final newline

D:\temp>cscript while.vbs
Calculate powers of 2

1       2       4       8       16      32      64      128
D:\temp>

Instead of testing "if a condition is true" sometimes the logic of the problem makes more sense to loop while a condition is not true. In the problem just shown we increment a counter (i) and loop "while i is less than 8." But we could also loop "while i does not equal 8" which would look like this

Do While i <> 8
    Wscript.StdOut.Write 2^i & Chr(9)
    i = i + 1
Loop

But that can get awkward for more complex conditions, and we do not usually speak and write English that way. VBScript also has the Do Until loop for situations where we want to "loop until a condition is true. So the problem could also be written

Do Until i = 8
    ...

In the previous examples all the tests were made at the beginning of the loop, which is called a pre testloop. If for any reason the test fails, the code on the body of the loop never gets executed. Sometimes the code in the loop must be executed at least one time, perhaps to get input to see if we want to continue, which is a post test loop.

Do                                      Do
    statement(s)                            statement(s)
    ...                                     ...
Loop While condition                    Loop Until condition

Recall the Select Case example above where we asked the user for input and continued looping until they got the checkered flag. Here is another example where we add a series of numbers.

' sumloop.vbs
'   add numbers until user says no
'   demonstrate Do While

Option Explicit

Dim n, sum, choice

Wscript.StdOut.Write "Enter first number: "     ' first number to get started
sum = CDbl(Wscript.StdIn.ReadLine)              ' convert input to double
                                                '   precision floating point type
Do
    Wscript.StdOut.Write "Enter next number: "
    n = Wscript.StdIn.ReadLine                  ' next number

    sum = sum + n                               ' compute running sum of numbers
    Wscript.Echo "Sum = " & sum                 '   and display the sum
    Wscript.StdOut.Write "Continue? (y/n)"
    choice = Wscript.StdIn.ReadLine             ' add another number?
} Loop While choice = "y" OR choice = "Y"       ' loop while choice is y or Y

D:\temp>cscript sumloop.vbs
Enter first number: 4.5
Enter next number: 3.3
Sum = 7.8
Continue? (y/n)y
Enter next number: 5
Sum = 12.8
Continue? (y/n)Y
Enter next number: 2
Sum = 14.8
Continue? (y/n)n

D:\temp>

We don't know how many numbers there will be, but there must be at least 2 since it makes no sense to add 1 number. After we get the first number we ask the user for the next number and add it to the sum. The sequence "next number" and "add to sum" do not change regardless how many numbers we add, so we put them inside a loop. However, we must read and add the "next number" at least once, so the post test loop is a good choice. The remaining logic in the loop is perhaps the most important; setting up a condition that will ultimately end the loop.

Notice that we use the logical operator OR to test for lower or upper case 'Y'. Notice also that the test is not very "bullet proof:" any letter other than 'y' or 'Y' will exit the loop. And if a user answers "yes" or "yea, sure," the loop will exit as well. These shortcomings can be solved with additional processing of the user's answer by extracting the first character of the input, and making additional tests for 'n' or 'N' if we decide that is important. Frequently we are much more concerned about one of the choices. For example, if the question is "Are you sure you want to format the disk?" we can be safe and only continue with a 'y' or 'Y'.

[ TOP ]



<Do While/Until> For <For Each>

When the number of iterations is known in advance, as in the powers of 2 example above, a For loop is usually better.

For variable = start To end [Step n]
    statement(s)
    ...
Next

Step is optional and defaults to 1 if omitted. If Step is negative the loop steps "backward." End must be greater than start for positive values of n and must be less than start for negative n's.

Here is the powers of 2 example rewritten as a For loop.

' for.vbs
' demonstrate For

Option Explicit

Dim i

Wscript.Echo "Calculate powers of 2"
Wscript.Echo                                ' blank line for spacing

For i = 0 To 7
    Wscript.StdOut.Write 2^i & Chr(9)       ' ASCII 9 is the TAB character
Next
Wscript.Echo                                ' send final newline

D:\temp>cscript for.vbs
Calculate powers of 2

1       2       4       8       16      32      64      128

D:\temp>

Notice how the code is "self-documenting" and much simpler: the variable i is initialized as part of the loop structure, and it is automatically incremented. A common source of errors is incorrectly adjusting While and Until loop variables (or forgetting them completely!) resulting in an infinite loop. Unless we are foolish enough to mess with the loop variable inside the For loop it is almost impossible to get into trouble with a For loop.

[ TOP ]



<Do While/Until> <For> For Each

For loops are ideally suited for processing arrays since we always know how many elements an array contains at any given time. For example, to print a list of names in a list we can write

Dim friends, i

friends = Array("Rocky", "Bullwinkle", "Boris", "Natasha", "Peabody", "Sherman")

For i = 0 To UBound(friends)
    Wscript.Echo friends( i )       ' displays Rocky and his friends
Next

Processing collections like the array above is common enough that VBScript has provides the For Each loop for collection iteration:

For Each variable In collection
    statement(s)                    ' process variable
    ...
Next

' foreach.vbs
' process array with For Each loop

Option Explicit

Dim friends, i

friends = Array("Rocky", "Bullwinkle", "Boris", "Natasha", "Peabody", "Sherman")

For Each i In friends
    Wscript.Echo i
Next

D:\temp>cscript foreach.vbs
Rocky
Bullwinkle
Boris
Natasha
Peabody
Sherman

D:\temp>

Just as For cleaned up and simplified While/Until for more specialized looping conditions, so For Each further simplifies loops for (admittedly even more) specialized conditions. It just so happens that these "specialized loops," iterating over collections, is really quite common. If you can get to your data (and that is, after all, the reason you submit yourself to this!) without initializing, setting, and incrementing counters and indices, then there is less opportunity to introduce bugs and errors. Be aware, however, that the For Each loop is also more limited: you do not have an index to the collection elements, and the elements are "read only" (you cannot modify the collection in a For Each loop).

[ TOP ]



Text & String Processing

Scripting languages typically work with text most of the time; 90% is a common estimate. ASCII text can be an array of individual characters, but is usually treated as a string of characters, commonly read from files. In a VBScript reference (see the Books section) that lists language elements by category String Manipulation has 46 entries; the only major category with more items is the File System Object. While some of these elements are VBScript functions, many are WSH objects including a rich set of Regular Expression methods.

As discussed earlier Windows Script Host executes scripts with one of two applications, the console host cscript.exe and the GUI host wscript.exe. Recall that some Wscript objects, such as references to the StdIn and StdOut streams, are not compatible with the GUI host. Recall also that the Wscript.FullName property returns the full path name of the executing host. The following script introduces the VBScript Instr() function as well as some additional arguments to the MsgBox() function.

' whathost.vbs
'
' Query Wscript.FullName property to determine what host is executing
'  our script; if not cscript host then return with error message.
' ----------------------------------------------------------------------

' If Instr() returns 0 then "cscript.exe" is not the host,
'   alert the user and return

If Instr(1, WScript.FullName, "cscript.exe", vbTextCompare) = 0 then
    MsgBox " Host: " & WScript.FullName & vbCRLF & _
           "This script must be executed by cscript.exe", _
           vbCritical, _
           "Error: " & Wscript.ScriptFullName

    Wscript.Quit(1)                         ' return error code to caller
End If

' Host is cscript.exe, OK to continue with script

Wscript.Echo "Host: " & WScript.FullName
Wscript.StdOut.WriteLine "OK to reference Wscript.StdIn and Wscript.StdOut"
Wscript.Echo
Wscript.Echo "Press ENTER to continue..."
Wscript.StdIn.ReadLine

If executed by the GUI host (e.g. the user double-clicks the script file name in Windows Explorer) we get the following error message:

whathost.vbs error message from GUI host

If executed by the console/command line host the script runs normally:

D:\temp>cscript whathost.vbs
Host: C:\WINNT\system32\cscript.exe
OK to reference Wscript.StdIn and Wscript.StdOut

Press ENTER to continue...


D:\temp\>

The Instr() function searches for a sub string within a bigger string, starting at the index specified in the first argument. For backward compatibility to earlier versions of Basic the string functions use 1-based indexes, which is a constant source of confusion and errors in VBScript (as in all dialects of Basic). WSH object methods that are not part of the core VBScript language are 0-based. We want to see if the sub string "cscript.exe" is in the longer string returned by the Wscript.FullName property. If it is, the index will be some number greater than 0. If Instr() returns 0 we know cscript.exe is not our host, so we display an error message in a message box (because we know we are in the GUI) and abort the script. The call to Wsript.Quit(1) sends a "return code" to the calling process; typically 0 means success and anything else signals an error.

If the script is executed by the GUI host we alert the user with an error message. We could just say something like "Try again," but it is better to provide some information so people don't keep banging away with the same input and get the same error. First we echo the output of Wscript.FullName so the user can see what host actually executed the script, then we tell them the correct host to use. In message boxes we have to explicitly include newline characters (Carriage Return + LineFeed in Windows) in our output string, so we use the VBScript global constant vbCRLF. We could also concatenate the ASCII characters with the Chr() function: Chr(13) & Chr(10). We also include an argument, again using a global constant, to indicate what type of icon we want in the message box. Finally we add a title to the message box to impart some more information: the full path name of the script that caused the error. Line continuation characters are used to make the code easier to read.

The final call to Wscript.StdIn.ReadLine is simply a means to pause the script. If you are certain the script will always be executed in a console window with the command cscript script_name this is not needed. However, if the script is executed via the Open with Command Prompt Context Menu item from Windows Explorer (right-click on script file name) it will open a console window, execute the script, and close the console in a flash before you can see any output. ReadLine waits for user input to continue. In this case we don't bother saving the input in a variable; the user can simply hit the ENTER key (or enter their name if it makes them feel good).

Windows Explorer 'Open with Command Prompt' context menu
Windows Explorer Open with Command Prompt context menu

Here is another example showing the Left(), Mid(), and Right() functions to extract sub strings from a fixed-width record (fields are specified by fixed column indexes), and use of the Trim() function to remove leading and trailing white space. Look up each function in the Windows Script Host help file to see the required and optional parameters.

' substr.vbs
'
' Demo Mid() function to extract sub string
' ----------------------------------------------------------------------

Option Explicit
Dim recordStr, fName, lName, address, city, state

' remember: VBScript string functions index from 1
'                     1         2         3         4         5         6
'            123456789012345678901234567890123456789012345678901234567890
recordStr = "Rocky       Squirrel  1 Hero Way        Frostbite Falls  MN"

fName   = Trim(Left(recordStr, 12))         ' Trim white space from Left string
lName   = Trim(Mid(recordStr, 13, 8))       ' Mid() using start index and length
address = Trim(Mid(recordStr, 23, 41-23))   ' length argument as an expression
city    = Trim(Mid(recordStr, 41, 58-41))

Wscript.Echo "First Name: ", fName
Wscript.Echo "Last Name:  ", lName
Wscript.Echo "Address:    ", address
Wscript.Echo "City/State: ", city & ", " & Right(recordStr, 2)

D:\temp>cscript substr.vbs
First Name:  Rocky
Last Name:   Squirrel
Address:     1 Hero Way
City/State:  Frostbite Falls, MN
D:\temp\>

[ TOP ]



Where to Next?

Copy the trivial examples on this page (copy and paste directly from your browser or download the source code) into a text editor and get them to run on your own system. Better yet, type them in from scratch; you will be surprised how much more you learn by typing in source code as opposed to cutting and pasting. Sort of like rewriting your class notes... Then make some changes: modify the user prompts, test for different conditions, modify the loops (count down, count by 2's, 3's, etc.)

Design and write a 4-function calculator. Write an algorithm to prompt the user for 2 numbers and whether she wants to add, subtract, divide, or multiply. Write the program and test it. Add detection for an attempt to divide by zero. When that is working see if you can wrap the whole thing in a loop that lets the user do additional calculations until she wants to quit.

Explore the string functions, and try to figure out file input and output using the FileSystemObject (subject of the next installment of this guide... when I get time).

Explore Regular Expressions ( WSH RegExp object) and the WSH Dictionary object. Regular expressions have been an important feature of the Unix operating system utilities and scripting languages (shell scripts, Sed, AWK, Perl, etc) for years and are finally being incorporated in recent Microsoft technologies including WSH and .NET. Andrew Clinick, Microsoft Script Technology Program Manager (1999), said in an article "Regular expressions are to strings what math is to numbers." RegEx coverage in the WSH Help system is limited, but a start, and the 2 books mentioned above have a good introduction. WSH Regular Expression support is "Perl 5 compatible," which is very complete.See Microsoft Beefs Up VBScript with Regular Expressions (Vernon W. Hui, Microsoft Corporation, May 10, 1999).

WSH Dictionary objects support associative arrays (hash data type in Perl). Associative arrays "associate" a key string index with an array value rather than a numerical index as in normal arrays. Take, for example, student test scores where we keep 2 arrays synchronized:

student = Array("Rocky", "Bullwinkle", "Boris", "Natasha")
score = Array(93, 88, 100, 65)

' get a student's score
Wscript.StdOut.Write "Score for " & student(1)
Wscript.StdOut.WriteLine " = " & score(1)

The same data implemented as an associative array (WSH Dictionary object):

Set studentScore = CreateObject("Scripting.Dictionary")

studentScore.Add "Rocky", 93        ' one way to add new key-value pairs,
studentScore.Add "Bullwinkle", 88   '   error if key already exits
studentScore.Item("Boris") = 100    ' another way to insert elements, if key
studentScore.Item("Natasha") = 65   '   exists over-writes existing value

' get a student's score
name = "Boris"
Wscript.StdOut.Write "Score for " & name
Wscript.StdOut.WriteLine " = " & studentScore.Item( name )

Familiarity with the Dictionary object will help make sense of the FileSystemObject collection object interfaces.

[ TOP ]



Links & Resources <Books> <WSH Help> <Thoughts>

[ TOP ]



<Links> Books <WSH Help> <Thoughts>

Unlike other languages, you won't find a huge selection of books for Windows Script Host, and most of the VBScript books cover the Web page and browser scripting commands. Here are 2 books that cover the scripting host and VBScript (one also covers a bit of JScript) in a tutorial "how to program style" and one that is a VBScript reference.

Windows 2000 Windows Script Host
Tim Hill
New Riders Publishing, 1999
ISBN: 1-5787-9139-2
Powell's
Best Book Buys
Excellent overall coverage of Windows Script Host and VBScript including a major section (5 chapters) on objects, classes, and Object Oriented Design (OOD).
Over 100 pages of "cookbook" scripts.
Covers VBScript only using .vbs files
Windows Script Host
Peter G. Aitken
Prentice Hall PTR, 2001
ISBN: 0-1302-8701-6
Powell's
Best Book Buys
Less thorough coverage than Windows 2000 Windows Script Host , however better suited to a "non programmer."
Covers VBScript and JScript as well as examples of .wsf files and using multiple languages in one script.
Vbscript in a Nutshell
Paul Lomax, Matt Childs, & Ron Petrusha
O'Reilly & Associates, 2000
ISBN: 1-5659-2720-6
Powell's
Best Book Buys
Typical O'Reilly Nutshell format:
First 8 chapters (~ 175 pages) tutorial in nature, however prior programming knowledge assumed. Chapters on language basics and data types plus the 4 main VBScript environments: Active Server Pages (ASP), Outlook, Windows Script Host, and Internet Explorer. Remaining single chapter (~ 250 pages) is the language reference.
Appendix listing language elements by category is particularly useful.

[ TOP ]



<Links> <Books> WSH Help System <Thoughts>

Windows Script Host documentation was virtually non existent until quite recently; the current documentation, in the format of a single Windows Help file, is very thorough, although still organized a bit odd. If you have a relatively recent installation of Windows you should have a Windows Script Host help file (or files). However, if you installed a more recent version of WSH as part of your Windows Update routine or directly from the Microsoft site, your help file might not match the most recent version of WSH. Under a normal setup your WSH help should be found in this Start Menu path:

Start > Programs > Microsoft Windows Script.

You can view the online documentation or download it for installation on your system at the Microsoft Windows Script Web site.

There is also a collection of sample scripts available on line and for download in Windows Help format. See the Links & Resources section for links to the Script Center Resources and look for Script Repository. I installed the Script Repository help file in the same directory as the WSH main help file and added a link in my Start Menu system for easy access.

[ TOP ]



<Links> <Books> <WSH Help> Final Thoughts

The only way to learn a programming language is to jump in and write code. Look at examples in books, articles, and online tutorials. Look at the sample scripts at the Microsoft TechNet site (see the Links & Resources section) or download the Script Repository file. Type them in a text editor and run them. Then look up what you don't understand in the Windows Script Host Help system and try to figure out what is going on. Pretty soon you will be looking up less and understanding more. You can do it! Think of it as a different kind of cross-word puzzle, or a new game..

[ TOP ]



Example Source Code

All example VBScript programs in this guide begin with a comment identifying the name of a file available for download. All files are in the archive http://www.mhuffman.com/notes/language/src_vbs/vbs_examples.zip.

[ TOP ]



Copyright Notice

Introduction to VBScript & WSH Copyright © 2003 Michael B. Huffman

The author gives general permission to copy and distribute this document in any medium provided that all copies contain an acknowledgement of authorship and the URL of the original document:  http://www.mhuffman.com/notes/language/vbs_intro.htm

The permission granted above does not imply permission to distribute this document in a modified form or as a translation.
Comments, corrections, and suggestions for improvement always appreciated.

Mike Huffman:  mike@mhuffman.com

[ TOP ]