Scripting Solutions with WSH and COM: Have Agents Work for You, Part 1

Downloads
21283.zip

Windows Script Host

In Window Script Host (WSH) scripts, systems administrators often use VBScript's InputBox function to receive information (e.g., logon information) from users and VBScript's MsgBox function and WSH's WScript::Echo method to provide information (e.g., error messages, which can often be obscure) to users. If you want your scripts to provide and receive information in a clear, attention-grabbing way, you can use Microsoft Agent 2.0.

Microsoft Agent consists of COM automation objects that let you use automated characters such as Genie and Merlin to visually and audibly provide and receive information on screen. Microsoft Agent even lets you use the Microsoft Speech Recognition Engine for Speech Input to provide customized audible messages. (Although Microsoft Agent provides this capability, I cover only the simpler visual-related technology in this column.) Because Microsoft Agent consists of COM automation objects, using this technology is a great way to learn how to use these objects in scripts—and to have some fun. Before I show you how to use them, though, you first need to download and install Microsoft Agent.

Obtaining the Technology
To run scripts that call the Microsoft Agent COM automation objects on a machine, you must install Microsoft Agent on that machine. To find out how to install this technology, go to http://msdn.microsoft.com/msagent/c-frame.htm?/msagent/default.asp. This page is Microsoft's table of contents for all topics related to Microsoft Agent on the Microsoft Developers Network (MSDN). From there, you can download the installation files, find out the details about how to automate the agent, and investigate UIs.

I suggest that you first download the Microsoft Agent core components, then download the four animated characters (Genie, Merlin, Robby, and Peedy). To install the core components and characters, you need Windows XP, Windows 2000, Windows NT, Windows Me, or Windows 9x; Microsoft Internet Explorer (IE) 3.02 or later; 16MB of RAM, including 1MB free for core installation; and 2MB to 4MB of RAM extra per character for installation. You don't need a sound card, but having a sound card makes the characters more interesting because they can give their message audibly.

Working with Agents
Microsoft Agent installs its files in the \%windir%\msagent\chars folder. Using the characters, or agents, is fairly easy, but you need to know two simple rules. First, the script you write will execute faster than the agents can act. As soon as your script terminates, the agents disappear. The implication of this behavior is that you need a special way to make your script wait until the last agent command has executed; otherwise, the agents won't carry out your instructions. Second, if you want to have two characters on the screen, you must make sure that they wait for each other and don't try to speak or arrive on screen at the same time.

To activate the animated characters, the first task is to instantiate the agents. The code that Listing 1 shows instantiates all four characters. This code doesn't display the agents on screen; the code simply instantiates the agents so that you can issue commands to them.

You begin the instantiation code by declaring several variables: a variable for each character, a variable for the path to each character, and a variable for the generic Agent object. Next, as callout A in Listing 1 shows, you create a generic agent-controlling object into which you can later plug the characters. The variable AgentControl receives a created automation object of the Agent.Control.1 class. The WScript::CreateObject function's optional second parameter sets an event handler called MyAgentEvent_, which I'll explain in a moment. You then check whether the agent control that you received is a valid object. If the agent control is a valid object, you set the connected attribute to True on the object. Then you're ready to start loading characters.

Next, you expand the paths for each agent that you want to use. Note that the paths aren't constants. Because the \%windir% path differs in different Windows versions, you can use the WshShell::ExpandEnvironmentStrings function to expand the paths correctly.

When you have the paths and a generic agent-controlling object, you can load the characters. This process involves two steps for each character. To load characters, you first use the Characters::Load method on the AgentControl object to pass in the character's textual name and its full path. You then pass the character object into a sensibly named variable of your choice (e.g., Robby) so that you can act on it. You can now issue commands such as Robby.Speak rather than AgentControl.Characters("Robby").Speak.

Using ActivateAgent
Listing 2 shows the same code inside a VBScript function called ActivateAgent. This function performs the same instantiation as the code in Listing 1. You can use this function to avoid issuing the same commands several times to instantiate different agent characters.

To use the ActivateAgent function in a script, you add it to the end of the script. Then, at the beginning of the script, you declare your variables. Listing 3 shows sample declaration code.

Adding the Loop and Event Handler
After you add the ActivateAgent function to instantiate the characters, you need to add a loop and an event handler to the script. The loop makes your script wait until the last character has executed its last command before terminating. Without this loop, you'll see only a brief flicker of animation on screen because the script terminates before the characters can say anything (or even fully appear).

Listing 4 contains the loop code you need to add after the last line of agent code. This code continues to loop until the final agent command has executed. At that point, the loop ends—and so does your script.

As the code at callout A in Listing 4 shows, you first set the LastCommand variable to the last command that you give to an agent. The last command is usually Hide, which removes the character from the screen gracefully with animation. After setting the LastCommand variable, you add the loop. This loop iterates until the bolFinished value changes to True.

At this point, the loop is infinite because you don't have any code to set the bolFinished value to True. In other words, the loop will never end, which means that your script will never end. Fortunately, Windows is an event-driven system. Events can fire while the loop executes and thereby prompt the bolFinished value to change to True. To achieve such a change, you use the event handler that Listing 5 shows. An event handler is a subroutine that specifies the action to perform when the specified event occurs. You place the event-handler subroutine that Listing 5 shows after the ActivateAgent function in your script.

The script calls the event-handler subroutine after an agent executes a command. The agent passes the command that it just ran to the subroutine as the strAgentCommand parameter. The subroutine then determines whether the strAgentCommand parameter's value matches the LastCommand variable's value. If the values match, the script changes the bolFinished value to True, prompting the loop and the script to end. If the values don't match, the loop continues.

The script in Listing 6 shows how all the pieces fit together. If you run this script, a Genie appears in a cloud of smoke, greets the user, says "Hello There!" then disappears in a cloud of smoke.

Here's how the script works. It begins by declaring the variables that the ActivateAgent function needs to instantiate the Genie character. Next, the script uses the Show, Play, Speak, and Hide methods. The Show method displays the character (in this case, Genie) and uses the relevant animation for that character. The Play method lets the character demonstrate a gesture (in this case, the Greet gesture). The Speak method lets the character relay a message (in this case, Hello There!) both audibly and in a speech bubble. As I mentioned earlier, the Hide method removes the character. After executing the Genie.Hide command and setting that command to the LastCommand variable, the script includes the loop code, ActivateAgent function, and event-handler subroutine.

What Not to Do
Microsoft Agent has a few pitfalls to be careful of. The problematic code that Listing 7 shows demonstrates some of these pitfalls. This code activates two characters: Genie and Peedy. Note that in Listing 7, I didn't include the ActivateAgent function and event-handler subroutine to save space—the errors don't relate to that missing code.

The code at callout A in Listing 7 uses the Show, MoveTo, Play, Speak, and Hide methods with the Genie and Peedy characters. (The MoveTo method moves the character to the specified XY coordinates.) In theory, this code has no problems. However, in practice, the code has three problems:

  1. Both characters appear on screen at the same time and in the same space.
  2. Only Genie speaks, even though Peedy's speech bubble appears.
  3. Peedy disappears too quickly—in other words, the script doesn't wait for Peedy's Hide animation before it exits.

Let's deal with Problem 3 first because it's easy to fix. The code at callout A in Listing 7 forces Peedy off the screen during the Greet gesture because Genie's Hide animation had already finished. To fix this problem, you change the code so that the last two lines of callout A are

Genie.Hide
Set LastCommand = Peedy.Hide

The lesson here is that getting the correct order is important.

Problems 1 and 2 occur for the same reason: The characters aren't giving each other enough time to do their bit. To solve these problems, you use the Wait method, which tells one agent to wait for the action of another agent to finish. You pass in the action that you want the second agent to wait for as the parameter to the call. For example, to wait for Genie to move before Peedy appears, you change the second line of callout A to

Peedy.Wait Genie.MoveTo (200,200)

(Note that you need to put the MoveTo parameters in parentheses because the script is passing the result into another method.) The simple delay that this change causes solves both problems. Now both characters can work their magic without affecting each other.

In the Code Library on the Windows Scripting Solutions Web site (http://www.winscriptingsolutions.com), you'll find the corrected version of the code in Listing 7. This script, TwoCharacters.vbs, includes not only the changes but also the ActivateAgent function and event-handler subroutine.

Extending What You've Learned
Next month, I'll delve further into the art of agents, including more pitfalls to avoid. Until then, explore the Microsoft Agent documentation to discover all the automation tricks that you can perform with Microsoft Agent.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish