Recipe 11.8 Check to See if an Application Is Already Running
11.8.1 Problem
You need to start up other Windows
programs from within your Access applicationfor instance, to
send data to Excel or to format a report in Word. If you just use the
Shell command to start these programs, you may end up with multiple
instances of the application. How can you tell if an application is
already running before you attempt to start it?
11.8.2 Solution
There are a number of solutions to this problem, and none,
unfortunately, are as easy as you might like. To ask Windows whether
Excel is currently running and receive an answer, you must know the
Windows class name for the main window of the application. This
solution explains the format of the question and how to ask it. In
addition, it demonstrates how to switch to a running application from
your Access application.If you have code that interacts
with applications external to Access, it is often useful to be able
to determine whether the application is running. The sample form,
frmAppsRunning (Figure 11-10), asks Windows the
question, "Is this app running?"
for each of six predefined window classes, and you can add one more
of your own. For each application that frmAppsRunning finds, it fills
in the window handle (hWnd) column and the window caption column on
the form. The AppActivate command in Access requires that you know
the exact title of the window, so this form uses code from Chapter 4 (in basAccessCaption) to retrieve the
caption for each running application. Finally, you can click on any
of the enabled buttons in the righthand column to switch to the
running application.
Figure 11-10. frmAppsRunning shows the state of certain applications

Try the sample form with Microsoft applications you have installed.
Press F1 to bring up Help, and then switch back to Access and click
on the Search button on the sample form. This will reinitiate the
search for active applications, and it will find
WINHELP.EXE running. Click on the question-mark
icon to switch back to WinHelp.Follow these steps to include this functionality in your own
applications:
- Import the modules listed in Table 11-9 from
11-08.MDB into your application.
Module | Contains |
---|---|
basCaption | acbGetAccessCaption , acbGetWindowCaption , acbSetAccessCaption |
basUsage | acbIsAppLoaded |
- To be able to ask Windows the
question, "Is some application
running?", you'll need to know the
Windows class name for the main window of the application. Table 11-10 lists the names for several Windows
applications.
Application | Class name |
---|---|
Access (all versions) | OMain |
Excel (all versions) | XLMain |
Explorer | ExploreWClass |
Outlook (all versions) | rrctrl_renwnd32 |
Notepad | Notepad |
PowerPoint 2003 | PP11FrameClass |
WordPad | WordPadClass |
Microsoft Word (all versions) | OpusApp |
- The class names are somewhat arbitrary. Because
they're assigned by the development staff, not by
the marketing or documentation departments, class names often reflect the
project's code name or the state of mind of the
developer.
Finding Class NamesThere are many ways to find the class names for applications' main windows. The simplest is to use the sample form for the Solution in Recipe 11.9, which displays a list of open windows and their class names. If you want to know the class name for a specific application, open it and run the sample form. The second column will list the class name for you. |
- To check whether a given application is currently running, use the
acbIsAppLoaded function in basUsage. Pass a class
name to this function as a parameter, and it returns the window
handle of the application if it's running, or 0 if
it's not. For example, this will return a nonzero
value if Microsoft Word is currently running (note that the class
names are not case-sensitive):hWnd = acbIsAppRunning("opusapp")
- Once you know the window handle for the
application, you can use the AppActivate command in Access to make
that application active. To do this, you'll need to
know the exact window caption. To make that easier, you can call the
acbGetWindowCaption function in basCaption before attempting to
activate the application. For example, this code will switch to
Excel, if it's running:Dim hWnd as Integer
hWnd = acbIsAppLoaded("XLMain")
If hWnd <> 0 Then
AppActivate acbGetWindowCaption(hWnd)
End If - If the application you want to
activate isn't currently running
(acbIsAppLoaded returned 0), use the
Shell command to start it. In this case,
you'll need to know the DOS executable filename for
the given application (EXCEL.EXE , for example).
The example form doesn't attempt to load the
applications if they aren't already loaded, but your
own application can load the program as needed.
11.8.3 Discussion
The acbIsAppLoaded function couldn't be simpler: It
calls a single Windows API function. The entire routine looks like
this:
Function acbIsAppLoaded (ByVal varClassName As Variant) As Long
If IsNull(varClassName) Then
acbIsAppLoaded = 0
Else
acbIsAppLoaded = acb_apiFindWindow(CStr(varClassName), 0&)
End If
End Function
This routine allows you
to pass in a class name. If the class name isn't
null, the function calls the FindWindow API function (aliased as
acb_apiFindWindow), which takes a class name and
returns the window handle of the first instance of that class it
finds. acbIsAppLoaded returns that handle to its
caller.This example uses the following code
from basCaption to determine the caption of a
window, given its window handle. Although this code
isn't the focus of this section,
you'll need to include it if you want to find a
window's caption.
Declare Function acb_apiSetWindowText Lib "user32" _
Alias "SetWindowTextA" (ByVal hwnd As Long, _
ByVal lpString As String) As Long
Declare Function acb_apiGetWindowText _
Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, _
ByVal lpString As String, ByVal aint As Long) As Long
Public Function acbGetWindowCaption(ByVal hwnd As Long) As Variant
' Get any window's caption, given its hWnd.
Dim strBuffer As String
Dim intLen As Integer
Const acbcMaxLen = 128
If hwnd <> 0 Then
strBuffer = Space(acbcMaxLen)
intLen = acb_apiGetWindowText(hwnd, strBuffer, acbcMaxLen)
acbGetWindowCaption = Left$(strBuffer, intLen)
End If
End Function
Don't expect acbIsAppLoaded to
distinguish between multiple copies of the same application. That is,
if you have two copies of Notepad running, you can't
count on acbIsAppLoaded to return the handle to a
specific instance of Notepad: it will return the handle of the first
instance it comes across. But that shouldn't bother
you, as you're simply trying to find out if
any copy of the application is currently
running.