[ Go to January 1997 Table of Contents ]

Power Windows /
Karen Kenworthy

Mow Down Redundant Programs
Stop multiple copies of the same program from launching.

Insufficient memory? That can't be happening! I've got a hefty 16 megs on this machine. I wonder what programs are running? Oops--two copies of my Web browser and three copies of my word processor. I sure don't remember starting those. Yikes! Eight copies of Solitaire! It's no wonder I'm out of RAM."

Judging from my mail, many of you have experienced this memory mishap. Some programs take steps to prevent you from opening more than one copy of themselves. If you try to launch it, the would-be second copy either displays an error message, or simply activates the sleeping first copy. In either case, the second copy (what programmers call a "second instance" of a program) quietly goes away.

But many other programs aren't so considerate. They happily let us run as many copies of themselves as our RAM will hold-even if we wish they wouldn't. For those applications, I've written PWOne, a little utility that puts us back in control. With it, we can decide which apps can't run more than one copy of themselves. You can download the utility here. It includes a 16-bit Visual Basic 3.0 (VB3), and a 32-bit Visual Basic 4.0 (VB4), version of PWOne. Both versions include the executable file (PWONE.EXE) and complete source code.

Target practice

To use PWONE.EXE, simply run it in place of your regular program (what I'll call the target program). PWOne will immediately search Windows' list of running programs (the Master List). If the target program is among them, PWOne activates the already running copy and restores the target program's main window (if it's minimized). If the target program is nowhere to be found, PWOne will launch it.

To perform its magic, PWOne needs two pieces of information: the title bar text that the target application displays when running and the command used to launch the target application. As you've probably guessed, both tidbits are passed to PWOne via command-line parameters.

If you're running Windows 95, right-click on the shortcut that currently runs the target program. When the shortcut's context menu appears, select Properties. Click on the tab labeled Shortcut, and take a look at the shortcut's "Target" entry. This entry is the command currently used to launch the target program.

We need to make two changes to this entry. First, at the beginning, insert "PWOne " (be sure to include a space between the e and the close quote). This causes the shortcut to run PWOne instead of the target program.

Immediately after "PWOne " insert the text displayed by the target application in its title bar. Be sure to enclose the text within quotation marks (for example, "Netscape" or "Microsoft Word"). If you need to specify a quotation mark within the text, type two sets of quotation marks in a row. You don't need to include the entire title bar text-just enough to uniquely identify the target app's main window. Also, don't worry about case. PWOne's search of Windows' Master List is case-independent.

Next, click on the Properties dialog box's OK button. If your shortcut now displays PWOne's WinMag icon and you want to change it, edit its properties by clicking on the Change Icon button on the Shortcut tab of the Properties dialog. In the space provided, enter the full pathname of your target application, press Enter, then click on the icon you prefer from the list provided.

If you're running Windows 3.x, the procedure is almost identical. But instead of modifying the Target entry of a shortcut's properties, modify the Command Line entry of the Program Manager icon used to launch the target program. To do so, click once on the icon to select it, then press Alt+Enter. The changes that should be made to the Command Line entry are exactly the same as those described above.

Time for a test drive

If you've placed PWONE.EXE in your WINDOWS directory or anywhere else in your path, you're now ready to take it for a test drive. First, double-click on the shortcut or icon you've just modified. If no copies of the target application are already running, the target app should load normally. Now, minimize the target application's main window, so it only appears as a button on Win95's taskbar, or as an icon on your Win3.x desktop.

Bring it home by double-clicking on the target application's shortcut or icon again. Now, instead of a new copy of the target, you should see the original copy with its main window restored to its non-minimized size.

Under the hood

Let's take a look under PWOne's hood. Like most of our Power Windows utilities, PWOne is written in Visual Basic. Though the version we'll be discussing is written in VB4, PWOne can also be written in VB3. Even though it's a 16-bit application, the VB3 version will work under Windows 95.

Most Windows programs display lots of information and allow the user to interact with the on-screen display. One of the program's windows (what VB calls "forms") is designated the Startup Form. This means that form is displayed first, and its code determines when other forms are loaded and displayed. But PWOne does all its work behind the scenes. That's why PWOne doesn't have a Startup Form. Instead, it has a Startup Subroutine named Main.

Main resides in a module, a place where VB stores code not associated with any form or window. To create a module, select Module from VB4's Insert menu, or New Module from VB3's File menu.

The text of Main is shown in the sidebar "A Peek at PWONE." As you can see, it's an ordinary VB subroutine, which is not passed any parameters. Lines 2 through 4 declare the three variables used by Main: Title, ToDo and Result. Title is used to store the target program's title bar text. ToDo stores the command line needed to launch the target application. Result is what programmers often call a temporary variable. It's used in one of Main's statements, to receive a value returned by a function when it doesn't matter what value is returned.

Main begins its real work at line 5. This statement calls a mystery subroutine named Parse, and passes it our variables Title and ToDo. As we'll see next month, Parse is a relatively large subroutine that examines the command line used to launch PWOne. As you'll recall, that command line includes the target application's title bar text and the command used to launch the target app. Parse locates each of these command-line parameters and places them in Title and ToDo, respectively, before exiting.

In line 6, Main calls another subroutine, ChkMstrList, passing it the title bar text just provided by Parse. ChkMstrList searches Windows' Master List for windows whose title bar text matches that found in Title. If a match is found, the program's full title bar is returned and stored in Title. If no match is found, ChkMstrList returns an empty string ("").

Decision time

Now we come to a fork in the road. The If statement that begins in line 7 contains two branches. One, consisting of lines 8 through 10, holds statements that are executed if ChkMstrList found a match (Title > ""). The net effect of these statements will be to activate the running copy of the target application and restore its main window.

First, VB's built-in subroutine AppActivate is called, passing it the value of Title returned by ChkMstrList. This function causes the application with that title bar text to be "activated," or receive Windows' input focus. Until the focus is changed again, all keystrokes and mouse events will be processed by the activated application. Next, we call the built-in subroutine DoEvents. This subroutine "yields" the CPU to other running programs, allowing them to get some work done, rather than waiting for processor time. We're doing that now in order to allow time for our requested change of input focus to take effect.

Finally, in line 10, the built-in subroutine SendKeys is called. This procedure allows us to send "keystrokes" to the program with the input focus. The program will process them exactly as if they had been typed at the computer's keyboard. The characters we're sending are "% R." The percent sign is really a special character that tells SendKeys to simulate the Alt key being pressed. So the keystrokes seen by the target application are actually Alt+Space, then R. As you know, Alt+Space causes a program to display its System, or Control, menu (the one that appears when you click on the spacebar icon at the extreme left side of the title bar). And R selects "Restore" from that menu. The end result is the program's main window is restored to its normal size, if it's currently minimized. If not, the keystrokes sent by SendKeys will have no effect.

Line 12 contains the one statement that executes when the target application isn't already running. The built-in Shell function runs the command specified in ToDo-opening the app-and returns a "Task ID" that we store in Result. You can use the Task ID in certain Windows API calls to obtain information about the program just started, but we don't need it for our purposes.

Finally we come to line 14, Main's last executable statement. The built-in VB procedure End causes PWOne to terminate, allowing the target application to take center stage.

Stay tuned

There's more to say about PWOne, but it will have to wait until next month. That's when we'll take a look at Parse. Until then, try to finish that game of Solitaire before you start the next one.

A Peek at PWONE
1	Sub Main()
2		Dim Title As String
3		Dim ToDo As String
4		Dim Result As Long

5		Parse Title, ToDo
6		Title = ChkMstrList(Title)
7		If Title > "" Then
8			AppActivate Title
9			DoEvents
10			SendKeys "% R", True
11		Else
12			Result = Shell(ToDo, 1)
13		End If
14		End
15	End Sub

Line numbers are shown for informational purposes only.

Contributing Editor Karen Kenworthy is the author of Visual Basic for Applications, Revealed! (Prima Publishing, 1994) and the manager of WINDOWS Magazine forums on America Online and CompuServe. Contact Karen in the "Power Windows" topic of these areas, or via e-mail at karenk@winmag.com.