|[ Team LiB ]|
Recipe 11.8 Check to See if an Application Is Already Running
You need to start up other Windows programs from within your Access application—for 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?
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.
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:
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.
|[ Team LiB ]|