[ Go to February 1997 Table of Contents ]|
Command lines and parsing hold the secrets to how a program is launched.
Back when CPUs glowed in the dark, programs received their first dose of information from a command line. These elder command lines served the same purpose as modern command lines seen by DOS and Windows: They launched a program, and provided it with some initial information via switch settings and other parameters.
A program, in turn, can locate and understand the information provided by the command line via parsing, or breaking the command line down into its individual parts.
PWOne, last month's Power Windows utility, is a good example of a program that relies on command-line parsing. (You can download PWOne from the WinMag online sites listed on page 24.)
PWOne prevents selected applications from running more than one copy at a time. This utility needs two pieces of information to do its job. First, it must know some of the text the target application displays in its title bar. PWOne doesn't need the entire title bar text-just enough to distinguish the target application's main window from all other windows open at the time. Second, PWOne needs to know the command you're currently using to start the target application.
Both pieces of information are passed to PWOne the old-fashioned way-via its command line. The target application's title bar text comes first, surrounded by a pair of quotation marks. This is followed by the command used to launch the target. A typical PWOne command line reads something like PWOne.exe "Solitaire" c:\Windows\Sol.exe.
Visual Basic, the language used to write PWOne, offers some help in decoding this information. It takes the original command line used to start PWOne, and strips PWOne's name from the beginning. It then stores the rest of the command line in a special variable named Command$
To break Command$ apart, isolating each parameter, we must look for special markers called delimiters. Each parameter has two delimiters, one to mark the beginning of the parameter, the other to mark its end. In the case of the first parameter, the target's title bar text, the delimiters are obvious: They're the two quotation marks surrounding the text. Everything in between is the actual parameter.
The delimiters marking the location of the second parameter, the command used to launch the target application, are a bit more subtle. The first nonspace character after the first parameter indicates the beginning of the second parameter, while the end of the command line marks the second parameter's end.
Once we've identified each parameter's delimiters, we inspect the command line, one character at a time, proceeding from left to right. When we come to the delimiter that marks the first parameter's beginning, we start copying characters from the command line to the variable we've set aside to store the first parameter. We continue copying characters until we reach the delimiter that marks the first parameter's end. We then continue inspecting the command line, looking for the beginning of the second parameter. We also copy parameter two (one character at a time) to its own special variable. When we arrive at parameter two's end delimiter, our job is done.
PWOne's parsing routine (named Parse) is shown in the sidebar "A Flawless Routine." As you see in line 1, the two variables that hold the parameters (Title and ToDo) are passed to the parsing routine. In lines 2 through 5, Parse declares a few variables of its own: Cmd, CmdLen, Quote and i.
Line 6 stores a copy of the original command line in our variable Cmd. We also "pad" our copy, adding one additional space character at the end. Next, we store the length of the original command line in CmdLen, and a single quotation mark character in the variable named Quote.
Now we find our first delimiter, the quotation mark that indicates the beginning of the title bar text. That's accomplished by the InStr statement in line 9. VB's InStr function examines one string (in this case our padded copy of the command line, Cmd), looking for the first occurrence of a second string (Quote). If the search is successful, the location of the match is returned and stored in the variable named i.
But what if InStr's search fails? That means the command line contains no quotation marks. InStr will return a negative number, which is an invalid location. Even worse, if there are no quotation marks, the routine can't find the target application's title bar text. Without that text, PWOne can't do its job. Therefore, in line 10, we test the value returned by InStr. If it's less than zero, PWOne displays its only form, frmAbout. Besides the usual copyright and version information, this "About PWOne" dialog box also includes a short description of how to use PWOne. Once we click on the dialog box's OK button, the dialog disappears and PWOne ends.
Beginning at line 15 we see what the Parse subroutine does when the first quotation mark is found. First, it clears the variable Title to hold our newfound title bar text. Next, the value stored in i is increased by one. That's because i currently holds the location of the first quotation mark, while the title bar text actually begins one character later (the quotation mark isn't part of the text)
Lines 17 through 29 contain a large loop, instructions that are executed repeatedly until the title bar text has been completely copied to the Title variable. In line 18, we use VB's built-in Mid$ function to see if the current character is a quotation mark. If so, we may have found all the title bar text and might be ready to locate parameter two-the command used to launch the target application. But if the current character isn't a quotation mark, the subroutine proceeds to line 26, where the current character is added to the end of Title. Once that's done, i is increased by one, and the loop continues, processing the next character in Cmd.
In a perfect world, we could just end our search for the title bar text as soon as a second quotation mark is found. But what if the title bar text actually contains a quotation mark? For that situation, Parse allows you to specify a quotation mark inside the title bar text by placing two quotation marks in a row.
For a closer look, check out lines 19 through 21. Line 19 "peeks," looking into the next character of Cmd (at location i + 1) to see if it's a quotation mark. This is why we had to pad Cmd by adding an extra space. In other words, we can now be sure the location we peek at always exists. If our peek reveals a quotation mark, it's copied to Title and the search for the title bar text's ending delimiter continues. If the peek reveals anything else, the title bar text has been found and copied, so the loop ends (line 23)
Now, we're ready for parameter two. As you'll recall, it begins with the first nonspace character after the end of parameter one. Lines 30 through 34 take care of this detail, first by increasing the value stored in i by one (to "step over" the quotation mark that signals the end of parameter one), then examining each successive character of Cmd until a nonspace character is found. If we reach the end of the command line before our search succeeds, we once again display our helpful About form (lines 35 through 39)
Finally, in line 40, our variable ToDo is erased, preparing it to receive the second parameter. The actual copying of the target application's command to ToDo occurs in the short loop consisting of lines 41 through 44.
If you have any questions about PWOne, command lines or parsing, look me up on America Online at email@example.com.
Karen Kenworthy is the author of Visual Basic for Applications, Revealed! (Prima Publishing, 1994). She is also a contributing editor to WINDOWS Magazine and the manager of WINDOWS Magazine Online on America Online and CompuServe. Contact Karen in the "Power Windows" topic of these areas, or care of the editor at the e-mail addresses here.
Sidebar -- A Solid Routine
PWOne is a good example of a program that relies on command-line parsing. (Note: The line numbers are for reference only.)
1 Sub Parse(Title As String, ToDo As String)
2 Dim Cmd As String
3 Dim CmdLen As Integer
4 Dim Quote As String
5 Dim i As Integer
6 Cmd = Command$ + " " ' Pad Command Line
7 CmdLen = Len(Command$)
8 Quote = Chr$(34) ' Store " char for future use
9 i = InStr(1, Cmd, Quote) ' Find first Quote
10 If ( <&EQUALS; 0&RPAR; Then &APOSTROPHE; Oops, no quotes</P>
11 MsgBox "No title bar text specified", 16, "PWOne"
12 frmAbout.Show 1
14 End If
15 Title = ""
16 i = i + 1
17 Do While ( <&EQUALS; CmdLen&RPAR;</P>
18 If Mid$(Cmd, i, 1) = Quote Then
19 If Mid$(Cmd, i + 1, 1) = Quote Then
20 Title = Title + Quote
21 i = i + 1
23 Exit Do ' found ending quote
24 End If
26 Title = Title + Mid$(Cmd, i, 1)
27 End If
28 i = i + 1
30 i = i + 1 ' Step over Title's trailing quote
31 Do While ( <&EQUALS; CmdLen&RPAR;</P>
32 If Mid$(Cmd, i, 1) <>" " Then Exit Do</P>
33 i = i + 1
>35 If i CmdLen Then
36 MsgBox "No Command specified", 16, "PWOne"
37 frmAbout.Show 1
39 End If
40 ToDo = ""
41 Do While ( <&EQUALS; CmdLen&RPAR;</P>
42 ToDo = ToDo + Mid$(Cmd, i, 1)
43 i = i + 1
45 End Sub