Many of the scripts you write will require some form of user input. Whether the user is supplying some direction for the script or merely providing information that the script cannot determine on its own, this is a very common and useful technique. We’re going to explore some of the more common ways to handle user input.
There are basically two different ways to request user input for your script. The first is by using run time parameters supplied by the user at the time of script execution. The second is by accepting a user’s response to a prompt during the script’s execution.
We’ll start by learning how to handle parameters that are passed as arguments during the script’s execution. WSH allows for argument passing in two ways. You can supply them in the command line used to execute the script or you can drag-and-drop files onto a script’s icon.
The first is the method of choice for running a script with the Cscript engine and the second is the better choice for executing through the Wscript engine. However the two methods are not exclusive to these recommendations.
Using drag-and-drop to pass files or folders to a script will execute the script using the default scripting engine.
WSH provides a native object for us to handle these arguments called the WshArguments object. The WshArguments object returns a read-only collection of items that were passed during execution. The WshArguments object is returned by the Wscript object’s Arguments property.
object.Arguments
The process of handling the object and arguments is the same regardless of which method was used to pass them. Let’s take a look at the methods and properties provided by the WshArguments object.
Methods
object.Count
object.Item([Index])
Properties
object.length
The WshArguments object contains a collection of argument items. The Count method is used to return a Long value indicating the number if items in the collection. The Item method is used to return a specific item in the collection corresponding to the supplied zero-based Index value.
The length property returns a Long value indicating the number of items in the collection. For consistency when using Jscript, this length property should be typed in lower case.
Set colArgs = Wscript.Arguments
For Each Arg In colArgs
Wscript.Echo Arg
Next
This simple loop will iterate through each of the supplied arguments and Echo them back to the user. This is a very basic method of processing these arguments.
Let’s take a look at how to handle command line parameters that are supplied when calling a script. The user will simply append some information to the command line at the time of execution.
Multiple command line parameters are separated by spaces so any argument that contains spaces should be enclosed in quotation marks.
Let’s create a very simple script that accepts a text string parameter. We’ll simply Echo the text string back to the user. Copy the following text into any text editor such as Notepad and save it as echoscript.vbs.
Set colArgs = Wscript.Arguments
Wscript.Echo colArgs.Item(0)
This script simply assumes that there will be only one item in the colArgs collection. This string is returned using the Echo command. Let’s see how it works by taking a look at the following command line and results.
C:>cscript.exe arguments.vbs “Hello World!”
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Hello World!
There you have it. Our string was echoed back exactly as expected. What would happen if we tried this without the required quotation marks?
C:>cscript.exe arguments.vbs Hello World!
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Hello
Oops! Cscript encountered a space and processed the words as two separate parameters. Our script only echoes the argument located at Item 0. In other words, it will only return the first word.
So it’s obvious at this point that we need to process each of these arguments individually. We’ll do that by creating a loop.
Set colArgs = Wscript.Arguments
For i = 0 To colArgs.Count - 1
strText = strText & colArgs.Item(i) & " "
Next
Wscript.Echo strText
As you can see we’re looping through each item based on its index value. We used the Count method to determine how many times our loop needs to iterate. Don’t forget that indices are zero-based so our highest index value is our Count minus one.
There is one other important step that you should add to your scripts when dealing with arguments. What happens if the user doesn’t supply the required arguments? A little error-handling can both notify the user and also prevent unexpected errors.
If Wscript.Arguments.Count Then
Set colArgs = Wscript.Arguments
For i = 0 To colArgs.Count - 1
strText = strText & colArgs.Item(i) & " "
Next
Wscript.Echo strText
Else
Wscript.Echo "This script cannot be run without parameters."
End If
The Arguments object will always exist even if it is empty so we can build a simple If statement around the Count method. A count of 0 will be considered False while any other value will be considered True.
Sometimes it’s just not feasible to worry about what order the command line parameters are given in. Often there are optional command lines that can be left out by the user. This can make it very difficult to parse the arguments without writing a lot of extra code. Thankfully, WSH provides a way to make this a little easier.
object.Named
object.Item(Name)
WSH allows us to use a named argument. The Named property of the Arguments object returns a dictionary of named arguments. The Item method is used to grab those dictionary entries according to the supplied Name. Let’s write a script that accepts two command line parameters: a name and an age. The command line might look like this:
C:>cscript.exe namedargs.vbs /name:Nilpo /age:26
The command line above demonstrates the use of named arguments. Each argument is listed as a command line switch with a name-value pair. The name and values are separated by a colon. Don’t forget to surround the names or values in double quotes if they contain spaces. Now let’s take a look at the code.
Set dicNamedArgs = Wscript.Arguments.Named
strName = dicNamedArgs.Item("name")
strAge = dicNamedArgs.Item("age")
Wscript.Echo "Your name is " & strName & ". You are " & strAge & "."
What we’ve done here is quite simple. We’ve assigned the variable dicNamedArgs to our dictionary object. Then we call for each of the command line Items. If we run the example command line above, our output should look like this:
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Your name is Nilpo. You are 26.
Now try this example again with the same code. This time we’ll switch the order of the command line arguments. Because we’re calling by name, and not by order, our script will run perfectly.
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
Your name is Nilpo. You are 26.
Perfect! We got exactly the same output. Notice that it even ignored the extra command that it didn’t recognize. It’s also important to note that if two arguments have the same name, only the first will be processed. Any remaining arguments sharing that name will simply be ignored.
Maybe you want to prompt a user based on information gathered by the script. Or perhaps it’s just not feasible to use command line parameters. In either case, it’s sometimes useful to prompt for user input during the execution of a script. In Cscript this is done using StdIn and StdOut.
Those familiar with command line programming know that StdIn (standard input) and StdOut (standard output) are input and output in a command window, respectively. WSH makes these accessible through Wscript properties by the same name.
object.StdIn
object.StdOut
The StdIn property returns a read-only TextStream object from the Standard Input stream. The StdOut property returns a read-only TextStream object from the Standard Output stream. Both of these are only available when using the Cscript host.
All of the TextStream object methods and properties are available to us, but we’ll only focus on the most commonly used ones for our purposes.
Methods
object.ReadLine
object.Write(String)
Properties
object.AtEndOfStream
You should be familiar with these methods and properties from my Working With Text Files series, but here’s a quick recap. The ReadLine method returns a string containing the contents of the TextStream object. The AtEndOfStream property is available at every character position and returns true when the end of the text stream is reached. The Write method writes a supplied string to a TextStream object.
Before we can get a user’s input we first need to tell them what we want. We’re going to prompt them by writing to the command window’s standard output stream. This is done by connecting to the StdOut object. We then accept their input from the standard input stream by means of the StdIn object.
Wscript.StdOut.Write "What is your name? "
strName = Wscript.StdIn.ReadLine
Wscript.StdOut.WriteLine "You have indicated that your name is " & strName
This simple snippet will produce a prompt asking for the user’s name. Below is a sample output of what this script might look like when executed.
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
What is your name? Nilpo
You have indicated that your name is Nilpo
We can expand our example a little to show that these text strings can be manipulated just like any other strings. I’ll show you the difference between using the Echo method and StdOut.
Wscript.StdOut.Write "What is your name? "
strName = Wscript.StdIn.ReadLine
Wscript.Echo "How old are you? "
strAge = Wscript.StdIn.ReadLine
Wscript.StdOut.WriteLine "Your name is " & strName & ". You are " _
& strAge & "."
Here we’ve changed the code to also prompt for an age. Notice that the age prompt uses the Echo method rather than the StdOut object. Here’s how the output looks now.
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
What is your name? Nilpo
How old are you?
26
Your name is Nilpo. You are 26
You can see that I entered my age on the line beneath the age prompt. That’s because the Echo method always appends a string with a linefeed character which left the cursor on the next line.
Since the StdIn and StdOut objects are only available in Cscript, we have to find other ways of handling user input when using the Wscript engine. This is most easily done using VBscript's InputBox and MsgBox functions.
The InputBox first creates a dialog box with a text field for user input. Then, the user optionally enters information and then clicks either the OK or Cancel button. The InputBox function returns a string result after one of the buttons is pushed.
Pushing the Cancel button on an InputBox dialog will return an empty string regardless of what the text box contains.
The MsgBox function will create a dialog box without any method of user input. Message boxes are very flexible, allowing you to change both the message icon and the available buttons.
The InputBox function requires a Prompt string that will be presented to the user. The remaining attributes are all optional. The Title attribute is the string displayed as the dialog box title; the Xpos and Ypos are used to manually position the box from the left and top of the screen, respectively; and the Helpfile attribute specifies a help file associated with the input box. An optional context attribute can be used with the HelpFile attribute to indicate a specific context number in the help file.
Constant
Value
Button
VBOK
1
OK
VBCancel
2
Cancel
VBAbort
3
Abort
VBRetry
4
Retry
VBIgnore
5
Ignore
VBYes
6
Yes
VBNo
7
No
The MsgBox function’s only required attribute is the Prompt. The Title attribute provides a title for the dialog box. The Button attribute defines what buttons will be displayed. You can use a combination of either constants or values listed in the table below. The button attribute defaults to 0. The MsgBox function returns a value base upon the button pushed. The possible values are listed in the table to the left.
OPTIONAL BUTTON VALUE ARGUMENTS
CONSTANT
VALUE
DESCRIPTION
VBOKOnly
0
Show OK button
VBOKCancel
1
Show OK and Cancel
VBAbortRetryIgnore
2
Show Abort, Retry, Ignore
VBYesNoCancel
3
Show Yes, No, Cancel
VBYesNo
4
Show Yes and No
VBRetryCancel
5
Show Retry and Cancel
VBCritical
16
Show critical message icon
VBQuestion
32
Show warning query icon
VBExclamation
48
Show warning icon
VBInformation
64
Show information icon
VBDefaultButton1
0
First button is default
VBDefaultButton2
256
Second button is default
VBDefaultButton3
512
Third button is default
VBDefaultButton4
768
Fourth button is default
VBApplicationModal
0
User must respond before the application will continue
VBSystemModal
4096
User must respond before any application will continue
Let’s go back to one of our Cscript examples and rewrite it for Wscript. First, we’ll ask for the user’s name. Then, we’ll ask for their age. We’ll finish up by showing our results.
strName = InputBox("What is your name?", "About You", _
"Enter your name")
result = MsgBox("You have indicated that your name is " & strName _
& vbCr & "Is this correct?", VBYesNo + VBQuestion, _
"Please check your name")
strAge = InputBox("How old are you?", "About You", "Enter your age")
result = MsgBox("Your Name is " & strName & ". You are " & strAge _
& ".",, "Your Results")
This produces a series of input and message boxes to gather the user’s name and age. It finishes by displaying the results. There are a few things to note in this example. First, notice the two different ways we’ve called the MsgBox function. I’ve used a mixture of the optional attributes.
You should also notice the last message box. I’ve used the optional Title attribute but have not used the Button attribute. I included an extra comma to show where the Button attribute would have been. Even though the Button attribute is missing, the Title attribute must still be the third attribute passed to the function.
The first message box is used check that the name is correct. It doesn’t do much good if we don’t do something to handle the result.
strName = InputBox("What is your name?", "About You", _
"Enter your name")
result = MsgBox("You have indicated that your name is " & strName _
& vbCr & "Is this correct?", VBYesNo + VBQuestion, _
strAge = InputBox("How old are you?", "About You", "Enter your age")
result = MsgBox("Your Name is " & strName & ". You are " & strAge & _
".",, "Your Results")
I’ve added an If statement to check the result of the first message box. If the No button was pressed it notifies the user and ends the script. Notice that I’ve used the exact values to call this message box.
Although you can call the MsgBox function using either constants or values for the Button attribute you should maintain a sense of continuity in your script by using the same method throughout.
We should also add some code in case our user presses the Cancel button on any of our input boxes. To avoid stretching this code sample on forever I’m going to make use of a subroutine.
strName = InputBox("What is your name?", "About You", _
"Enter your name")
If strName = "" Then Call UserCancel
result = MsgBox("You have indicated that your name is " & strName _
& vbCr & "Is this correct?", VBYesNo + VBQuestion, _
"Please check your name")
If result = VBNo Then
result = MsgBox("Sorry. Please try again.", 16, _
"Program Terminated")
Wscript.Quit
End If
strAge = InputBox("How old are you?", "About You", "Enter your age")
If strAge = "" Then Call UserCancel
result = MsgBox("Your Name is " & strName & ". You are " & strAge & _
".",, "Your Results")
Sub UserCancel
result = MsgBox("You have chosen to end this program.", _
vbInformation, "Program Terminated")
Wscript.Quit
End Sub
If you’re using a message box that has multiple buttons, it may be easier to use a Select statement to check your answers.
It’s possible to use a Select statement to process message box results because the result constants actually represent the integer values.
Here’s a quick example of what that might look like. Try running it a few times and press each of the possible buttons.
result = MsgBox("Press a button", VBAbortRetryIgnore)
Select Case result
Case VBAbort
Wscript.Echo "You pressed Abort"
Case VBRetry
Wscript.Echo "You pressed Retry"
Case Else
Wscript.Echo "You pressed Ignore"
End Select
Now you’ve seen how to handle user input in both Cscript and Wscript using command line parameters when calling your script and by prompting for the information during execution. This can add a whole new dimension to your scripting practices. Thanks for reading once again. Until next time, keep coding!