Mr. Script
Scripting Serendipity
Finding out that .WSF scripts—based on XML—allow you to declare just about anything can be a flexible timesaver.
- By Chris Brooke
- 01/01/2002
Serendipity. The English author Horace Walpole coined the word in a letter
dated Jan. 28, 1754. It’s defined as an accidental, but fortunate, discovery.
Were I to equate the word to scripting, I might call it a pleasant byproduct
of a particular feature—one that might very well have slipped by unnoticed
and unused. Scripts in the .WSF format are based on XML. XML allows you
to declare virtually anything via an appropriate tag—things like objects.
Serendipity! The ease with which this is accomplished only adds
to its value. You may remember I used this technique before when I referenced
objects in my Windows Script Components (WSCs). Yes, just as .WSF scripts
share similarities in format with WSCs, they also include the ability
to place references to all sorts of objects—and the syntax is the same.
<?xml version=”1.0”?>
<package>
<comment>
Objects.wsf
This script demonstrates the ability to declare objects
For a particular job within .WSF files
</comment>
<job id="Count">
<object id=”objFSO”progid=
"Scripting.FileSystemObject"/>
<script language="VBScript">
<![CDATA[
msgbox objFSO.Drives.Count
]]>
</script>
</job>
</package>
This script creates a reference to the FileSystemObject and displays
the current number of drives known to the operating system (including
mapped network drives). As with everything in the world of scripting,
there are rules for using the <object>
tag:
- Each object must be declared inside the <job>
that will use it. You can’t declare objects for an entire <package>,
nor use an object declared inside another <job>.
- The tag’s usage is <object id="id"
progid="progid">
- The id for the object is the name of the variable you’ll use
to reference it within the script. Use this attribute in place of a
Dim statement. In fact, if you include a Dim statement for the included
object, it’ll reset the variable to “empty” and break your script.
- The progid of the object is in the standard libraryname.classname
format. If you need help figuring out this nomenclature for a particular
DLL, simply view it using our old, trusty pal, XRay.exe.
Using the <object> tag eliminates the
need to execute the following commands:
Dim objMyObject
Set objMyObject=CreateObject("Library.Class")
What’s The Hubbub… Bub?
“Hmmph! So what? So, we type only one line instead of two. Big deal!”
Well, the benefits of declaring objects in this manner reach a bit further
than that. By declaring the objects outside the script code, we gain the
advantage of what I call “pseudo-early binding.” As you know, VBScript
can only create objects using late binding—the objects are created as
needed, at runtime. By declaring these objects using the <object>
tag, memory is allocated while the script is loading, rather than during
script execution. Depending on how heavily you rely on objects (I use
them a lot), this can really speed up your scripts.
Speed is good, but there are even greater benefits. By placing the object
declarations at the <job> level, rather than the <script>
level, these objects are available to any and all individual scripts within
a job.
<?xml version="1.0"?>
<package>
<comment>
Objects2.wsf
Demonstrates how objects are available to all scripts
in the job
</comment>
<job id="FSO">
<object id="objFSO" progid="Scripting.FileSystemObject"/>
<object id="objShell" progid="WScript.Shell"/>
<script language="VBScript">
<![CDATA[
msgbox objFSO.Drives.Count
]]>
</script>
<script language=”JScript”>
<![CDATA[
var bDriveExists;
bDriveExists=objFSO.DriveExists("C:");
objShell.Popup(bDriveExists);
]]>
</script>
</job>
</package>
In this script, I have declared two objects: the FileSystemObject and
the WSHShell object. (The WSHShell objects allow me to display a pop-up
box in the JScript portion of the script. JScript doesn’t support msgbox.)
Both scripts were able to access data from the objects.
But Wait, It Gets Better!
Looking back on your homework, we created a .WSF script with multiple
jobs. Cool concept: One file, lots of scripts inside. Each job could contain
multiple scripts, but we really didn’t have any way to get them to work
together. Normally, in multilanguage scripts, all declared variables are
reset after the </script> tag is read.
This meant that every time we switched from VBScript to JScript we were
basically starting from scratch. Not so when using the <object>
tag. Because any script inside the <job>
can access these objects, we have a perfect opportunity to persist data
between scripts.
How, you ask? Go back to those wonders of modern technology: Windows
Script Components! Simply create a WSC for persisting data (i.e. create
a component with a bunch of properties—no methods are necessary). Once
your component is registered, you can reference it via the <object>
tag, just like any other object. Voila! A ready-made data-persister
(probably not really a word, but who cares?)
Here’s an example of a WSC created to persist a single value:
<?xml version=”1.0”?>
<component>
<registration
description="MyDataComponent"
progid="MyDataComponent.WSC"
version="1.00"
classid="{0ed4d22b-6bc6-4f0a-8981-328da463234b}"
>
</registration>
<public>
<property name="MyProp1"/>
</public>
</component>
<text>
And here’s the script to use it:
<?xml version=”1.0”?>
<package>
<comment>
DataPersist.wsf
Demonstrates how objects can persist data
To all scripts in the job
</comment>
<job id="MDC">
<object id="objMDC" progid="MyDataComponent.WSC"/>
<script language="VBScript">
<![CDATA[
objMDC.MyProp1="Hello World!"
]]>
</script>
<script language="JScript">
<![CDATA[
WScript.Echo(objMDC.MyProp1);
]]>
</script>
</job>
</package>
Not bad, eh? All this functionality is made possible by just the <object>
tag! Next month, I’m going to take a look at some of the other tags you
can use in .WSF files to make things really interesting.
About the Author
Chris Brooke, MCSE, is a contributing editor for Redmond magazine and director of enterprise technology for ComponentSource. He specializes in development, integration services and network/Internet administration. Send questions or your favorite scripts to [email protected].