Building a library of reusable code is helpful because you don’t have to keep reinventing the wheel each time you automate a new task. If you want to use a scripting language to write reusable code, one option is to use Windows Script Components—WSC. (You can write reusable code several ways. To learn about the various options, see the sidebar "Is WSC Right for You?")
What Is WSC?
WSC is primarily a feature of Windows 2000 and Microsoft IIS 5.0, but you can install WSC in earlier Windows platforms as an add-on. To install WSC, you need to install either Microsoft Internet Explorer (IE) 5.0 or later or Windows Script (WS) 5.5, which contains WSC. You can download WS 5.5 from http://www.microsoft.com/msdownload/vbscript/scripting.asp. Although WSC is a native object of IE 4.0 and Windows 98, Win98’s WSC (formerly called XML Scriptlets) supports a slightly different syntax and isn’t fully compatible with Win2K’s WSC. In this article, I cover the Win2K syntax. For information about the Win98 syntax, see the Microsoft Developer Network (MSDN) article "Writing COM Objects with Scripting Languages".
A WSC object is basically a COM object made of scripting code. The WSC object works like a COM object. However, the WSC object isn’t a compiled binary file like most COM objects but rather an XML file that exposes a list of properties and methods that you implement through scripting code. You can use any scripting language to implement these methods and properties, as long as you run the code on a Windows-compliant scripting engine. IE 4.0 and later has such an engine for VBScript and JScript. Third-party engines for languages such as Perl, Rexx, and Python are available on the Internet.
To write a WSC object, you need to create an XML file that complies with a particular schema. This XML file has a .wsc extension and contains three types of information:
- The object’s description, which consists of the registration, programmatic identifier (ProgID), class identifier (CLSID), and version number
- The programming interface, which consists of the object’s methods, properties, and events
- The scripting code for each method, property, and event
A system-provided runtime engine processes the WSC object’s XML source code. You might be wondering how a COM-aware client can talk to a text-based file and treat that file like a compiled binary COM object. The executable modules (i.e., .dll or .exe files) that implement COM objects are pieces of compiled binary code that clients recognize. The executable module that implements WSC objects (i.e., the WSC runtime engine, which is a system file called scrobj.dll) is also a piece of compiled binary code that clients recognize. Clients can't perceive the difference between a WSC and COM object, but they recognize the appropriate compiled binary module when they attempt to instantiate a WSC or COM object.
When a client instantiates a WSC object, the client goes through the usual series of actions to instantiate a COM object. The client reads the path to the executable that renders the object (i.e., the WSC runtime engine) and starts talking to that engine. The engine acts like a proxy and makes the WSC object’s methods and properties available to clients. The engine resolves any method or property call in the scripting code.
Creating a WSC Object
Listing 1 presents a .wsc file that creates a simple WSC object that you can use to display a message box. The file includes XML tags that define the WSC object and its behavior. Because XML files are similar to HTML files, the XML tags are similar to HTML tags. Let's analyze the XML source code in detail.
The first line in Listing 1 declares the XML document compliant with version 1.0 of the XML standard. This directive doesn’t directly affect how the system treats the .wsc file.
As I mentioned earlier, a .wsc file contains three types of information: the WSC object’s
description, programming interface, and scripting code. You describe the object with the
Listing 1 contains the minimal content for the
If you're familiar with the COM fundamentals, you know that a generic COM object must have a 128-bit CLSID but the progID is optional. Because a WSC object is a COM object, the progID is theoretically optional. However, in practice, a progID is necessary because you’ll be using the WSC object as a COM automation object (i.e., a COM object that exposes methods and properties so that other applications can programmatically drive it). Without a progID, the WSC object is unusable because the CreateObject function needs the progID to instantiate the object for further use. Instead of omitting the progID, you can omit the CLSID in the
To expose their functionality, COM objects implement interfaces. All COM objects implement the basic IUnknown interface and make this interface available to callers. In addition, COM objects can implement and make available other interfaces. A WSC object can implement a limited number of interfaces. These interfaces fall into three groups:
- Interfaces needed for automation and event handling (i.e., automation interfaces)
- Interfaces needed for Active Server Pages (ASP)
- Interfaces needed for IE 5.0 behaviors
For now, I concentrate on how to create automation-interface WSC objects. I cover the ASP and IE interfaces later.
The WSC syntax doesn’t dictate that WSC objects implement an automation interface.
However, in practice, any WSC object must implement this interface. To declare the automation
interface, you use the
You can assign the
<property name="Title"> <get/> <!-- omit if write-only --> <put/> <!-- omit if read-only --> </property>
In addition to declaring the Title property and its privileges, the
The <script>: Tag
After you declare an WSC object’s methods, properties, and events, you need to define them in a <script>: block. For the MyComp.Hello object, you need to define the Say method and the Get and Put functions, as callout B in Listing 1 shows. However, before you can include these definitions, you first need to declare and initialize internal variable names for all the properties you declared in the
m_Title = ""
initializes that variable to an empty string.
With the properties’ internal variable names declared and initialized, you can include the definitions in the <script>: block. As callout B in Listing 1 shows, you can use the Function statement to define the methods and functions. (For information about how to use the Function statement, see "Understanding VBScript: Built-In and User-Defined Functions," October 1999.)
When most people define the Get and Put functions, they typically use the default names, but you can specify custom names. The default names for the Get and Put functions are get_Xxxx and put_Xxxx, where Xxxx is the name of the property. For example, the default Get and Put function names for the Title property are get_Title and put_Title.
To change the default names, you can use the Get and Put functions’ internalname attribute. Suppose you want to use the custom names of GetTitle and PutTitle instead of get_Title and put_Title. Instead of declaring <get/> and <put/> in the <public> block, you use the code
<property name="Title"> <get internalname="GetTitle" /> <put internalname="PutTitle" /> </property>
Then, in the <script>: block, you use the custom names instead of the standard names:
Function GetTitle() GetTitle = m_Title End Function Function PutTitle(newTitle) m_Title = newTitle End Function
With these changes in place, the WSC runtime engine will search for the custom names when it accesses the Title property for reading and writing.
When writing the scripting code for a WSC object, you need to keep in mind that you’re writing code within an XML file. Certain characters in the scripting language might also have special meanings in XML. For example, the ampersand (&) and caret (
<script language="VBScript"> <!\[CDATA\[ ' Scripting code goes here. \]\]> </script>
The scripting language’s parser engine then implements the methods and properties you define in the <script>: block. You aren’t restricted to using only one scripting language. The only reason why you might not want to mix languages is that keeping more parser engines in memory might affect overall performance.
Testing a WSC Object
Before you use a WSC object in production, you need to test it in a nonproduction environment. As with any other COM object, you must register a WSC object before you test and use it. You can register a WSC object two ways:
- Right-click the .wsc file, then select the Register menu command.
- Start the regsvr32.exe utility from the Run prompt or the MS-DOS console. You must pass the .wsc file’s fully qualified path to the utility.
During the registration process, the WSC runtime engine generates a CLSID for the object if you
didn’t include that information in the
You use a WSC object in code the same way you use any other COM automation object. You begin by using the CreateObject function to create an instance of the WSC object. For example, to instantiate the MyComp.Hello object, you can use the code
set obj = CreateObject("MyComp.Hello")
The client then talks to the WSC runtime engine, which, in turn, loads and interprets the associated .wsc file to expose the object’s methods and properties. You can now call any of the object’s methods or properties from any COM-aware client. For example, to call the MyComp.Hello object’s Say method and Title property, you can use the code
obj.Say "Hello world!" obj.Title = "Hi" obj.Say "Hello World again!"
Beyond the Automation Interface
Automation-interface WSC objects are only one type of WSC object you can create. You can create two more types of WSC objects: server-side objects that access the ASP object model and client-side objects that access the IE 5.0's Dynamic HTML (DHTML) object model. Although you can create a WSC object that has only an ASP interface or only an IE interface, you probably wouldn’t want to. Without the automation interface to provide methods and properties, the object would be unusable. Thus, here’s a look at how you can add an ASP or IE interface to a WSC object that already has an automation interface. (You can’t create a WSC object that has both an ASP and IE interface.)
Adding an ASP interface. With an ASP interface, your WSC object can access the Request, Response, Server, and other objects in the ASP object model. As a result, your WSC object can accomplish certain tasks within the IIS environment, such as reading parameters that browsers send and manipulating session information and response text in a client page.
To add an ASP interface to an automation-interface WSC object, you need to include the extra line
The best practice is to place this line before the <script>: block. This line tells the WSC runtime engine to obtain a reference to the ASP objects and add that reference to the script context. (The script context is an area of the memory that stores pointers to all the objects that the code can use.) After you declare that you want to access ASP objects, you can safely make calls to them.
Adding an IE interface. DHTML objects are special IE 5.0 COM objects that customize the behavior of HTML tags within a page. You can use DHTML objects to personalize the way in which one tag or all tags of a certain type work within a page. For example, you can use a DHTML object to automatically highlight links when a mouse passes over them without having to flood the page with scripting code. Basically, the DHTML object already contains all the scripting code for that behavior. You simply assign that behavior to any tag of that class as a Cascading Style Sheets (CSS) style.
To add an IE interface to an automation-interface WSC object, you need to include the extra line
Once again, the best practice is to place this line before the <script>: block. This line tells the WSC runtime engine to obtain a reference to the DHTML objects and add that reference to the script context.
Now that you understand the WSC basics, you might be interested in a couple of handy tools for WSC. These tools are the Windows Script Component Wizard and SAPIEN Technologies’ PrimalSCRIPT 2.0.
The Windows Script Component Wizard is a Microsoft tool that automates the process of creating a .wsc file. You just supply the needed information in a six-step process. After the wizard finishes, you have a working .wsc file that you can customize. In his column "Scripting Solutions with WSH and COM: Using WSC to Build a Progress Bar Dialog Box, Part 2" (October 2000), Alistair G. Lowe-Norris discusses how to use the wizard.
WS 5.5 includes the Windows Script Component Wizard, but you can download it separately from the Microsoft Scripting Web site. Go to http://msdn.microsoft.com/scripting/default.htm?/scripting/scriptlets/default.htm. In the menu on the right, click Downloads. The page that appears contains a link to download the wizard. The menu on the left also has a Documentation link that brings up a page with links to the WSC language reference and other supporting documentation.
PrimalSCRIPT 2.0 is a fully featured Windows Script Host (WSH) editor that specifically supports WSC. A free 30-day trial version is available (http://www.sapien.com/products.htm).
With these tools and a basic knowledge of WSC, you can start creating a library of reusable code. This library will save you much time and effort.