This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


This article assumes you're familiar with JScript
Download the code (10KB)

User Interaction with Windows Script Host
Michael Whalen

Windows Script Host 2.0 introduces the ability to use standard input/output streams. Now you can use WSH as a command-line batch language that interacts with the user.
As the popularity of Windows® Script Host (WSH) has grown, developers have placed more demands on its functionality. It's easy to write a simple administrative task using WSH—just type in a few lines of code and let it run. But what if you want that task to be a little more sophisticated? Maybe you want it to perform different tasks, depending on your mood (and the input you give the program).
      No problem—WSH can handle command-line arguments with ease. If this isn't enough and you want something that can interact with the user, WSH 2.0 lets you use the standard streams (stdio) to get the information that you need. Not pretty enough, you say? Well, what if you use Microsoft® Internet Explorer to put a nice GUI front-end on a WSH script? While you can use third-party controls to do all of these things, you can also accomplish them with what you have installed on your computer right now. And it's easy to implement, to boot.
      I'll present several different ways you can interact with the user by taking advantage of WSH. I won't describe the detailed inner workings of the applications; you can investigate that on your own, if you want. This article covers how to pull data from input and send it to output, all in a framework that will make it easy to add user interaction to any script you write.

Remember DOS? Say Hello to the Command Line
      Let's start with a simple command line. It's not very sexy, but in most cases it gets the job done. Say you're building a simple database of names and phone numbers. You need to write a quick utility that will add a name, delete a name, and look up a phone number.
      Now let's add a few constraints. The program must be usable by anyone, so you'll need to include a help screen. You also might want to add some fields later, so it has to be easily expandable. This isn't the only script you'll ever write either, so let's try to make the code as reusable as possible. And a little simple validation on the arguments would be nice. That's enough constraints; let's get started on the design.
      For the help screen, I'll employ a typical usage listing:


 Usage: phonebook [-H] | [-A] name num | [-D] [-L] name
 where
     -H    Show this message and quit
     -a    Adds a name
     -D    Deletes a name
     -L    Looks up a name (default)
     name  The name to process
     num   The phone number
You can probably write a script in under a minute that presents this text by building up a string and sending it to WScript.Echo. But you'll probably write very few applications with that particular usage, and you can't really reuse the text. If the parameters change, then you'll have to modify the string, making sure all of the formatting is still correct. This isn't a major problem, but why do it the easy way when you can do something much more valuable?
      Instead, let's write an argument handler routine. At the start of your script, pass the argument handler a few parameters. The handler can then validate your arguments, display usage, and maybe even store them in local variables for you. All of this can be done generically, so you won't have to write it again the next time you need an argument handler.
      Such an argument handler routine is shown in Figure 1, the Usage Demo. Here, I've written a database app using a WSH file and JScript®. This code sample simply stores the names in a text file that's in the same directory as the application. By using a WSH file, you can reuse the argument handler by including it as a file, rather than making it a block in each script file. What could be better than componentized scripting?

More Reminiscing… Menu-driven Software
      Now that you've got an argument handler and a simple application that lets you get a phone number, let's make it more powerful by adding addresses to the phonebook. An address takes some space—there's the street address, city, state, and ZIP code. It's probably more than you want to enter on a command line. You can do a little better by using standard streams to interact a little with the user.
      Figure 2demonstrates one way of doing this. Rather than filling out a command line, this program presents a menu to the user. After starting the program, the user gets the following menu:

 Phonebook - Main Menu
 [A]  Add a name
 [D]  Delete a name
 [L]  Look up a name
 [Q]  Quit Phonebook
 
 Command >
      Let's say the user selects a to add a name. The user now sees the following menu:

 Phonebook - Add a name
 [N]* Enter the name
 [P]* Enter the phone number
 [A]  Enter the street address
 [C]  Enter the city
 [S]  Enter the state
 [Z]  Enter the zip code
 [Q]  Quit and Save data
 [C]  Cancel (Data will not be saved)
 Items marked with a * are required but not completed
 Command >
      The user now selects N to enter the name, and the program prompts for it. After typing the name, the user returns to the previous menu and may select another command. The other commands will all basically operate in the same way; you can play with the example to see everything that it does.
      The power of this option is that the menu command is written as an object in JScript. This could also be done as a class in Visual Basic® Scripting Edition, also known as VBScript (see the Eric Lippert article, "Using Classes with VBScript 5.0," in this issue). By using the object-oriented nature of the language, you can make a generic object, pass it a few parameters, and voilà—instant menu. You can have the objects completely control the program flow. It all gets started by a single call to the top-level menu. By using WSH 2.0, you can use the standard streams to get the input from the user.
      You might notice that the code uses the argument handler functions from the previous example, but it doesn't take any arguments. If you look at the usage functions you'll see that it can check operating conditions while simultaneously checking the arguments. In this case, the script must be run with the console version of WSH, CScript, and not WScript; the standard streams require a console. This application indicates to the argument handler that it's console-based, so if it's run with WScript, a warning is presented to the user up front rather than popping an error on them when the code tries to grab the stdin stream. The truly ambitious might have the code restart the script under the correct environment.

Getting Back to Modern Techniques
      This is all well and good—if you don't mind writing applications that look like they're 20 years old. But in today's world graphics come as standard equipment, and if you don't have a graphical user interface on your program, you're just not trying hard enough. Well, WSH can do GUIs, too. There are a variety of third-party controls available that allow you to make forms and dialogs for use from scripts, but you can also do the same thing with something that you should already have on your machine: Internet Explorer.
      That's right, Internet Explorer allows you to script HTML, and WSH allows you to script Internet Explorer. Actually, it's COM that allows you to script Internet Explorer, but WSH is a great host for scripting COM objects because it has a simple method for sinking events.
      The GUI example expands on the phonebook of the previous examples. In Figure 3, not only do I store the name, address, and phone number, but I also keep track of favorite colors. This is just a simple example—you can get as complicated as you want. If you've seen it on the Web, you can do it with WSH. Being able to interface with Internet Explorer allows for very complex interaction with users; you can write a real, GUI-based app using a simple script language.
      The way this works is pretty basic. By attaching to a couple of the events that Internet Explorer fires, the script can control when the page gets updated and when the data is collected. There are more events that can be used, and more properties and methods that can be called, all of them useful in one way or another. Figure 4 is a brief description of some of the more useful ones, including those I've used in the example. The comments are my ideas for what to do with the events—go to MSDN™ (http://msdn.microsoft.com) to get a full description of the WebBrowser control and you'll probably come up with many more imaginative ideas.
      So now you know the WebBrowser control and its methods, properties, and events. But how do you use the WebBrowser in your script? Methods are easy—just call them. So are properties—just use them like you do variables. But what about events?
      You may have noticed in the code that I used WScript's CreateObject instead of the perfectly good object creation methods from the script engine. Normally, I encourage people to use the script engine's CreateObject method. CreateObject is more portable, so people porting a WSH script to ASP or Internet Explorer don't have to fix the code. But WScript's CreateObject has something that the VBScript CreateObject and the JScript ActiveXControl object don't: the ability to attach to events. By giving a second parameter to WScript.CreateObject, you assign a prefix to whatever object is created. In Figure 3, the prefix is ie_. So, to attach to an event, you would write a function called ie_EventName and WSH will automatically attach it to the event. This attachment is the key to making the user input idea possible.

Conclusion
      These examples are just a start. You can take them and add your own wonderful ideas. I've been perusing what developers are doing with scripting and WSH all over the world, and I'm often amazed at what they try to do. The really cool part is that it usually works. Sometimes it works too well—tasks that are really more suited to traditional development languages like C++ or Visual Basic are being done in script, simply because script can handle it. But scripting is appropriate for many large tasks. As long as you're writing full applications using WSH and the script engines, you might as well be using interactive techniques that make your applications look more polished.

MSDN
http://msdn.microsoft.com/voices/scripting.asp
and
http://msdn.microsoft.com/scripting/default.htm


From the November 1999 issue of Microsoft Internet Developer.