Quirky Quotes
Another common scripting error involves when and how to use quotes when those quotes are part of a string. Stewart says a classic example occurs when you're trying to run a command-line tool from VBScript code. If you need to specify a pathname when calling the command-line tool into action, you can run into problems. For example, suppose you want to open C:\My Files\org chart.bmp in Microsoft Paint. From a command-shell window, you'd run the command
mspaint.exe
"C:\My Files\org chart.bmp"
If you try to run this command from VBScript code without enclosing C:\My Files\org chart.bmp in quotes, as the code at callout A in Listing 1 shows, the command fails because of the space in the filename, and Paint gives you the error message C:\My.bmp was not found. However, if you simply add quotes around the pathname, as callout B shows, the command also fails because the scripting engine interprets the second quote (the quote that precedes the capital letter C:) as the end of the string. You'd receive the error message Expected end of statement.
You have several options for correcting this type of scripting problem. The easiest and safest approach is to escape—that is, flag—the character. VBScript lacks a true escape character (a character that's used to preserve the literal value of the next character that follows), so you use another quote. As callout C shows, escaping a quote with another quote can look bewildering. However, when you walk through each quote, the logic becomes apparent. The first quote in the code at callout C is easy to understand. The scripting engine interprets it as the beginning of a string. The scripting engine interprets the two-quote sequence before C: as follows: The first quote is escaping the second quote, so this sequence is interpreted as a literal quote. The scripting engine interprets the three-quote sequence as follows: The first quote is escaping the second quote, so the second quote is interpreted as a literal quote. The final quote in the three-quote sequence is read as the end of the string. For more information about escaping quotes, see the Windows Scripting Solutions article "Rem: Understanding Quotation Marks in VBScript," December 2002, InstantDoc ID 26975.
Another option is to use the numerical representation (aka the ANSI equivalent) for the embedded quote characters around the pathname. The ANSI equivalent is Chr(34). However, you can't simply replace the quotes with the ANSI equivalent. Instead, you must use the concatenation operator (&) to link together the ANSI equivalents and pathname. For this reason, using Chr(34) is complex and not recommended in most cases.
You have other options for handling quotes that are part of strings. For example, you can assign the quoted material to a variable. When the quoted material is a pathname, a common approach is to pass in the pathname from the command line when you launch the VBScript file.
You might find scripts that use single quotes (' ') instead of double quotes. This practice isn't recommended for several reasons. First, although a single quote is a valid character in VBScript, it's also the comment character (a character that indicates that the rest of the characters on that line are comments and not code). If the single quotes aren't embedded in a string that's enclosed in quotes, the scripting engine interprets the code that appears after the first single quote as a comment and the code fails. Second, in the WMI Query Language (WQL), the single quote is a reserved character (more about this topic shortly), which can introduce problems. Finally, although substituting single quotes for double quotes might work when you're displaying a message, this substitution doesn't work in every situation. For example, the code
Option Explicit
Dim objShell
Set objShell = _
CreateObject("WScript.Shell")
WScript.Echo _
"The 'org chart.bmp' file is open."
runs fine. However, if you try to use single quotes in the code at callout C in Listing 1, the code fails and returns an error message stating that you have an invalid path.
One final word of advice about quotes: Write scripts in a text editor. In "Quick Scripting Tips," Christa Anderson offers this sage advice: "Don't write them in a word processor, then copy them to a text editor for saving. Scripts use a lot of quotation marks. If your word processor converts straight quotes to smart quotes, when you copy the script to the text editor, junk characters will replace the quotes and the script won't work."
Special and Reserved Characters
Special characters and reserved characters can also cause problems in VBScript code. Special characters are typically any characters that aren't alphabetic or numeric. For example, the asterisk (*), question mark (?), tab, left angle bracket (<), and right angle bracket (>) are all special characters.
Some special characters are nonprintable, such as the tab. Other special characters are reserved for specific purposes. Which characters are reserved depends on what your code is doing. For example, when using VBScript regular expressions, you have many reserved characters—called metacharacters. These metacharacters include
$ ( ) * + . [ ] ? \ / ^ { } |
When you use XML tags in your VBScript code, the reserved characters you should watch for include
& ' < > "
Most of the time, you can use reserved characters in your code, but you need to escape them with the appropriate escape character. For example, suppose you want to use a regular expression to find where dollar signs ($) appear in text. Because $ is the metacharacter that tells VBScript's RegExp object to match the end of an input string, you need to escape it with a backslash (\), as this sample code shows:
Option Explicit
Dim objRegExp
Set objRegExp = _
CreateObject("VBScript.RegExp")
objRegExp.Pattern = "\$"
For XML tags, you can replace the reserved character with the appropriate escape sequence. For example, you can replace < with the < sequence and replace > with the > sequence.
Reserved characters' meanings aren't universal, which can also cause problems. A good example appears in the Microsoft article "Hey, Scripting Guy! How Can I Connect to a Folder When There's an Apostrophe in the Folder Name?" at http://www.microsoft.com/technet/scriptcenter/resources/qanda/dec04/hey1217.mspx. The Scripting Guy writes, "Ah, the apostrophe (also known as the single quote mark). It seems like such a simple little character, and yet it has probably caused scriptwriters more grief than any other character on the keyboard. (Yes, even more than ~.) The problem is that the apostrophe is a 'reserved' character in both VBScript and WMI; that means these scripting technologies want to reserve the use of the apostrophe for themselves. That's fine, except when dealing with folder names like Ken Myer's folder or people names like O'Donnell or O'Hara. You want to use the apostrophe, because how else can you write the name Ken Myer's Folder? Meanwhile, VBScript and WMI want exclusive use of the apostrophe for other reasons. As you might expect, that leads to problems."
As the Scripting Guy mentions, one way to solve this problem is to escape the apostrophe. In a WQL query, for example, you do so by preceding the apostrophe with a backslash. The Scripting Guy provides other valuable advice, so the article is definitely worth reading.
One way you can find reserved characters is to use the Escape and Unescape functions. Although these functions aren't documented in the WS 5.6 Help file, they're included in the documentation on the Microsoft Developer Network (MSDN) Web site at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/vtorifunctions.asp.
Microsoft designed the Escape and Unescape functions to make special characters in URLs viewable. However, you can use the Escape function for debugging VBScript files that might have special characters. The Escape function works by assessing a string one character at a time. When the function encounters a special character, it replaces the character with a percent sign (%) and the replaced character's hexadecimal number. For example, if you run the code
Option Explicit
Dim objShell
Set objShell = _
CreateObject("WScript.Shell")
WScript.Echo Escape("That darn cat!")
you get the results that Figure 1 shows. These results show that the space (escape code %20) and exclamation point (%21) are special characters. For more information about the Escape and Unescape functions, see the Windows Scripting Solutions article "Special Characters in VBScript," October 2004, InstantDoc ID 43751.
Finally, be aware that VBScript has reserved words as well as characters. For a list of the reserved words, see the Microsoft article at http://support.microsoft.com/default.aspx/kb/216528.
A Good Place to Start
The next time your VBScript script stops unexpectedly, you might want to examine the variables, error-handling statements, quotes, and special and reserved characters in your code for possible clues to the problem. However, be aware that VBScript works with many technologies (e.g., WMI, Active Directory Service Interfaces—ADSI), and each technology has its own set of problems. Thus, your debugging journey might have to take a different path. To help you in that journey, see the Web-exclusive sidebar "Notable Problems with WMI and ADSI" at http://www.windowsitpro.com, InstantDoc ID 46969 and the Learning Path box for additional debugging tips and tools.