An essential feature of Windows Script Host (WSH) is the Windows Script File (WSF) format, which Microsoft introduced in 1999 as part of WSH 2.0. Since then, WSF has proved to be helpful and powerful, but it's not a widely used feature, primarily because of the cumbersome XML syntax that surrounds the code. The beauty of WSH is its immediateness and intuitive code, which requires only a text editor and a console. XML adds an extra layer of code and requires an additional step when you write a script. At first sight, the WSF format seems more of a complication than a real help for script developerswhich is probably true if you only write and use simple scripts comprising a few calls. However, the more complex your scripts get, the more you need sophisticated tools, such as importable libraries of script functions, customizable resources, and predefined constants. The WSF format supports many additional features without touching the languages' syntax.
In this article, I use some quick and effective sample scripts to introduce you to the advantages of the WSF format. I also show you a handy tool that automatically translates existing VBScript and JScript code into a .wsf file.
WSF Advantages
When Microsoft started working on WSH 2.0, the WSH team needed to figure out a way to extend the programming power of scripting languages without heavily editing the language syntax or compromising WSH's inherent simplicity. VBScript and JScriptand, in general, all scripting languagesoffer a simple structure that doesn't provide for metainformation such as external source files, importable libraries and constants, and customizable resources. The growing demand for function-related enhancements put the WSH team on the road to introducing a new and more powerful file format. The team had three alternatives: Improve the language's syntax to accommodate new functions, extend the WSH object model, or give programmers a chance to create applications through small project files, in which the code is just one of the constituent elements (along with external resources).
The team chose the third option and arranged a simplified project file rendered through an XML schemaWSF. Basically, the WSF schema defines one or more jobs, each of which evaluates to an individual script. Each job has a <script> tag to define the code to run and a few extra tags to link the application to external resources. In WSH 5.6, Microsoft has further extended the schema to provide for named and unnamed arguments and usage information. In particular, the WSF format supports Include statements, type libraries, multiple language engines, and multiple jobs. For more information about the format, see the Microsoft article "Using Windows Script Files (.wsf)" (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/wsadvantagesofws.asp).
The key element of the schema is the job, the atomic element that forms a WSF application. A job is a collection of one or more script blocks, resources, and external links. You can have multiple script blocks in a .wsf file, and each block can target a different script engine (e.g., VBScript, JScript, Perl). You can define scripts in the same .wsf file or import them from an external file. The inability to include external files is a significant deficiency of both the JScript and VBScript programming interface. In other languages and development tools, you address this deficiency with special directives that instruct the compiler to access the specified external modules. In a WSF job, you use a tailor-made XML tagthe <script> tagto address the problem.
Converting VBScript Files to WSF Files
Here's how to rewrite a simple WSH application as a WSF job. The VBScript code
MsgBox "Hello from WSF"
is fully equivalent to the following WSF script:
<job>
<script language="VBScript">
MsgBox "Hello from WSF"
</script>
</job>
A straightforward way to translate the previous VBScript file into a more flexible .wsf file is to save the VBScript code to a file called hellowsf.vbs and run the following XML code:
<job>
<script language="VBScript" Src="hellowsf.vbs">
</script>
</job>
Both WSF approaches produce the same results.
Listing 1 shows the ScriptToWsf.vbs file. This script attempts to use the WScript's Arguments collection to read the name of the input VBScript or JScript file from the command line. In case of failure, the script prompts the user to type the name of the file to process. Next, the script creates an XML wrapper for the file with the same name but the .wsf extension. To do so, the script creates a new text file that has the same name and path as the specified file but with the .wsf extension. (The system will overwrite any existing file with the same name.) The script takes into account the extension of the file and sets the <script> tag to use the VBScript or the JScript language accordingly. I recommend placing the ScriptToWsf script (or a shortcut) on the desktop and dragging VBScript and JScript files onto it from a Windows Explorer window.
The ScriptToWsf script works with only VBScript and JScript files. However, extending it to support any other type of script you might be using doesn't require any special effort. Just extend the If statement or, better yet, convert it into a Select Case statement. For example, to have the script work with VBScript, JScript, and Perl files, you replace the code at callout A in Listing 1 with the code
Select Case ext
Case "js"
f.Write "JScript"
Case "vbs"
f.Write "VBScript"
Case "pl"
f.Write "Perl"
End Select
After you create a .wsf file that works exactly like the original script, you can more thoughtfully plan for extensions and enhancements. However, in this version of the ScriptToWsf script, be aware of a small, annoying requirement: For the code to work, you must have both the .wsf file and the original file available on the machine. The WSF code that the script generates is a mere shortcut that links to the original file as an external resource. Subsequently, if the original file is missing or can't be successfully resolved (i.e., it's a remote file and no connection is available), you'll get an error.