Newsletters #8

Since Microsoft released WSH 2.0, there is a possibility to use WSF (Windows Script Host) files for scripts. The WSH help just describes the elements you may use within WSF files (see also newsletter #4. Because WSF files are based on the XML format, it's possible to add a XML signature to these files (that allows you to process WSH files with XML tools like XML editors). Unfortunately Microsoft's WSH help file don't mention the consequences, if a user add such a signature.

Maybe you ask why I wrote a newsletter about that topic? Well, because I'm an ignorant and stupid guy! As I begun nearly a year ago to port my VBS and JS files to WSF it looked first as a trivial task. I just loaded the VBS or JS files using Notepad, added the WSF stuff <job> <script> ... </script></job>, saved the result into WSF files and executed the resulting file without (too much hassle). But after a while I recognized that WSF was XML based (at that time I have had not too much experience with XML). But as a careful man - to be compatible with future XML tools and probably WSH versions - I decided to add a XML signature (<? xml version="1.0" ?>) to all WSF files. And suddenly I ran into a lot of trouble, because most of my already ported scripts failed with syntax errors. In the first weeks I walked a very stoney way to find out the reasons for all thouse errors (WSH reported in many cases errors in line 0 character 1, that wasn't too helpful to me). At least I remembered me what I read one year ago about XML - and this was a break true for me. After I wrote my WSF files XML conform all trouble was gone. Fortunately I have had at this time not too many scripts to convert.

I mentioned that, because I'm probably not the only ignorant and stupid guy ;-). In the past I have seen many WSF sample files that are not XML conform (who cares - I guess most scripters haven't recognized that they are using XML in WSF files). And I have seen several WSH newgroup postings reporting trouble with WSF files (similar things that I observed a year ago). So I decided to write down a few tips about the "does and don'ts" in writing WSF files. I hope these tips will be helpful for others. So let's talk about the details.

(c) Günter Born, http://www.borncity.de

Warning: The material submitted as a newsletter comes AS-IS without any warranty of any kind. In no event shall the author be liable for damages and losses of any kind. The material discussed herein is copyrighted by the author. You get a free right to use it. This newsletter may be distribute freely as long as: a) the text remains intact and unmodified, b) a reference to the WSH Bazaar www.borncity.de is given and c) the newsletter is not shipped with other commercial material. If you like to ship the newsletter with CD-ROMs etc. please ask. Permission will be granted in normal cases, but I like to know where my material goes into.

How to sign WSF files and why?

A normal WSF file comes with a structure looking like to next listing.

<job id="T1">
<!-- by Günter Born -->
 <Script language="JScript" src="Hello.js "/>
 <Script language="VBScript">
  name = "world number 2"
  WScript.Echo "Hello, " & name
 </script>
</job>

The script shown above contains one Job with id "T1" that hosts two scripts. The first script element includes a file Hello.js whilst the second command creates a simple "Hello, world ..." dialog box using the Echo method. A small and simple program that may be executed with a double click. You will find similar samples in Microsoft's WSH help. So it may be not a major task to port your existing .js and .vbs files to .wsf files.

But there is a big pitfall: WSH will executed the sample shown above without any error message. So I guess many people will proceed like me to port their script files to .wsf files (just add the <job> and <script> stuff). On the other hand, the tags like <job> ... </job>, <script> ... </script> defines a structure based on XML (Extended Markup Language). The XML 1.0 specification allows you to write an xml file in a way shown above. But a better was is to add a signature to the first line of your XML document, informing the document's "reader" that the file is a XML document. Signing a file as a XML document may be done in a simple manner, you need to add only the statement:

<?xml version="1.0"?>

to the first line - that's all. Although this isn't required in WSH, it might be a wise decision to use this signature because:

As an experience pending more than 20 years in the computer industry I feelt that, if WSF files are based on the XML standard, we should follow this standard and write down all files according to this standard. This protects us against "surprises" in the near or far future.

So it's just a "keystroke" to add a XML signature to the sample WSF file. We need to insert the first line shown in the next code listing. This file will be detected by WSH and by other XML tools as a XML document that shall follow the XML 1.0 specification. If such a document is accepted from a so called XML parser, we can be sure that future XML parsers will also accept this file.

<?xml version="1.0"?>
<job id="T1">
<!-- by Günter Born -->
 <Script language="JScript" src="Hello.js "/>
 <Script language="VBScript">
  name = "world number 2"
  WScript.Echo "Hello, " & name
 </script>
</job>

If you try to execute the WSF script file given above in WSH 2.0, you will receive an error messages - WSH is unable to execute that script. After removing the first line, the file will be processed without trouble.

Note: I have added some errors by intension to the sample to show the consequences caused by the XML signature. I felt this is important, because I found similar code samples in Microsoft's WSH help file and in scripts written by others.

Does and don'ts in XML

If you sign a WSF file with a XML signature, you need to take care that the file's content follow the rules defined in the XML specification 1.0 (see www.w3c.org). Unfortunately this document isn't easy to read (it is written in a formal extended Backup Naur form - EBNF). As I started with WSF files it took me weeks to recognize what went wrong and until I remembered me about XML. (Now after writing an XML beginners guide I understand things even better.) Therefore I mentioned some rules how to write XML conform WSF files in my books Microsoft Windows Script Host 2.0 Developer's Guide (Microsoft Press USA) and Inside Windows Script Host 2. Auflage (Microsoft Press Germany).

But I wan't let you guess to much what's wrong with the code listing shown above. If you follow a few rules, you may be able to write also XML conform WSH files.

Rule 1: Use the right encoding

Well, probably you noticed that my christan name Günter has a German origin. And we European rebells use a few things in written text that is a bit distinct from good old english writing style. One nasty thing are accented characters like umlauts (Ä, ä, Ü, ü, Ö, ö, à, á and so on - it's not only in German, also Frensh, Italian, Spanish, Portugues, Polish, Tschech, Hungarian and other languages uses such characters). And this causes the first pitfall!

XML is Unicode based, and the UTF-8 character encoding is default for processing XML files. This character set contains mainly English characters (known from the ASCII code). Most WSH samples are written in English, and this language don't use accented characters. Therefore a signature like:

<?xml version="1.0"?>

is sufficient. The XML document just contains English characters that are supported in UTF-8 character encoding. Now let's have a closer look at my sample code given above:

<?xml version="1.0"?>
<job id="T1">
<!-- by Günter Born -->
...
</job>

This code snippet contains a comment <!-- .... --> which shall not be parsed from the XML processor. But before this file can be processed, all characters read from the WSF file need to be transfered to Unicode. Because UTF-8 doesn't support the character ü, WSH invokes an error dialog reporting an error in line 0, character 1 "can't convert to unicode". In a first step I strongly recommend that you should extend all your WSF script files with a XML signature supporting the character set you use (for us European rebells I recommend the West European character set). A better XML signature will look like:

<?xml version="1.0" encoding="ISO-8859-1"?>
<job id="T1">
<!-- by Günter Born -->
...
</job>

A statement <? .... ?> will be named in XML as a processing instruction, and the encoding attribute in the XML processing instruction allows the XML parser to use the extended character set for encoding. So Umlauts or other special characters within the XML document will be mapped properly to the Unicode character set.

Rule 2: Write wellformed XML documents

If you declare a WSF file as a XML document (using the XML processing instruction <?xml ...?>), this document need to follow a few XML rules. Such a document is called "well-formed". If the XML parser detectes the <?xml version=1.0"?> statement, a check for a well-formed document content is made. If the document contend isn't well-formed, the XML parser terminates with an error message. (A much more restrictive rule requires that the document is also a valid XML document. This means the XML document is at least well-formed, and it fulfills the rules given in the document's Document Type Definition DTD. The XML parser used by WSH checks a XML-document for well-formed-ness and also for validity.) The rules to write well-formed XML documents are not too difficult - and also the rules to create valid XML documents are not to complicated for the WSF DTD. Here are the rules you should follow to create your WSF files:

XML element within a WSH file need to be nested also according to a predefined manner (to creat a valid XML document that fits the rules defined in the WSF DTD). So a script element is always child of a job element. A job element may be the root element or may be a child of a package element. Here are the nestings allowed from the WSH dtd:

package: (comment | job)*
job (comment|script|object|reference|resource)*

The * indicates that multiple instances of the elements given in the brackets may occur (you may have multiple job elements, but only one package element. A comment element may be only child of a package element as well as a job element is only valid as a child of a package element).

Rule 3: Take care to "isolate" your script code

We can amend the short sample given above according to the rules in the previous section. Then your WSF file will be a well-formed XML document:

<?xml version="1.0" encoding="ISO-8859-1"?>
<job id="T1">
<!-- by Günter Born -->
 <script language="VBScript">
  name = "world number 2"
  WScript.Echo "Hello, " & name
 </script>
</job>

I removed also one <script> statement to simplify the sample. We used the encoding attribute and all elements are nested properly. Also the attribute values are enclosed in double-quotes. Nevertheless WSH will raise an error message during executing this WSF file. The error message indicates an entity value that isn't terminated with ; in line 6.

Note: Well, the first time I got this error message, I was heavy surprised. It was immediately after I decided to polish my VBScript code to use a good programming style in my script code. In my first VBScript samples I used "Hello, " + name for a string concatenation. Because the + operator is used for additions, a statement t = "12" + "10" will result in a value "22" and not in a string "1210". Therefore a better programming style uses t = "12" & "10" for string concatenation. After I changed that operation within my first script, an error message reporting an unterminated entity was the result.

Well, let's have a closer look what's wrong in line 6: WScript.Echo "Hello, " & name. We use the & operator for a string concatenation (that's allowed). Why in hell we get in trouble? XML know a thing called "entity". You can imagine an entity as a kind of placeholder, abbreviation or variable. If an entity is defined (implicite or explicite), you can insert the entity name in your XML document. If the XML parser recognizes an entity, it exchanges this placeholder with the entity value. For instance &gt; is a predefined entity that will be echanged with a > character during parsing. In XML documents you can declare for instance an entity name with a value "Günter Born". If you insert the entity &name; in your document, the parser exchanged &name; with the string Günter Born.

Now let's come back to the line given above. This line contains something like & name, which looks dammt like an entity. The blank between & and name is uses as a white space, the XML parser removes white spaces. So the result &name is an entity with a missing semicolon (the semicolon ; is the termination character for entities). Each time your script code contains such a construction, the XML parser used from WSH will raise an error. You can avoid this and other errors, if you instruct the XML parser not to parse the content of the script element. This may be done using the CDATA statement. The script code need to be written as:

<?xml version="1.0" encoding="ISO-8859-1"?>
<job id="T1">
<!-- by Günter Born -->
 <script language="VBScript">
 <![CDATA[
  name = "world number 2"
  WScript.Echo "Hello, " & name
 ]]>
 </script>
</job>

If the parser recognizes <![CDATA[ the following characters are not parsed until the pattern ]]> is found. Therefore you need to take care that such pattern doesn't occur within your script code (which is not highly likly, only a JScript construction if (a[idx[4]] > 10) contains this pattern).

Conclusion

WSF files offers intersting features within your script code (mixing JScript and VBScript code, including script files, accessing type libraries and so on). To be compatible with future developments I strongly recommend to take care about the XML rules and pitfalls I discussed above. If you write your WSF code according to the rules given above, your WSF scripts shall be "future compatible". For my own I created a simple template file that I use to create WSF files.

<?xml version="1.0" encoding="ISO-8859-1"?>
<package>
<job id="T1">
<!-- WSF template by Günter Born -->
<!-- File:                       -->
<!-- Author:                     -->

 <script language="VBScript">
 <![CDATA[
   Option Explicit
  ' insert your VBScript script code here
  ' WScript.Echo "Hello"
  ]]>
 </script>

 <script language="JScript">
  <![CDATA[
  // insert your JScript script code here
  //WScript.Echo ("Hello");
  ]]>
 </script>
 </job>
</package>

Show template: WSFTemplate.wsf download template: WSFTemplate.zip

You can register this template file as a new document template in Windows (for instance use Tweak UI). Then you are able to create a new .wsf file based on this template using the context menu's entry New command. You can use this template file also in PrimalSCRIPT editor (www.sapien.com) or in Microsoft Script Editor (MSE). I hope this short excerpt helps others to use WSF files withou further pain. Further details and other tricks may be found in my German Microsoft Press title Inside Windows Script Host, 2. Ausgabe and in my English Microsoft Press title Microsoft Windows Script Host 2.0 Developer's Guide (for details see).

Closing Note: Microsoft's help files for Windows Script Components (WSC) contains a much better discussion of XML style WSC file format than the help for WSF files. Also the samples given in WSC help are XML conform. I suggest to consult also the WSC help file to find out more about possible WSF elements (most elements useable in WSC files are also valid in WSF files).

Planned topics for newsletter #9 and future newsletters:

Enyoy scripting, till the next newsletter arrives...


(c) G. Born, 24 - October 2000 - www.borncity.de