Access Cookbook - Ken Getz [232]
The solution, then, is to be a good citizen, allowing Access its processing time. To do this, you must add a DoEvents statement inside the loop. This allows Access to continue working while this code loops, waiting for the application you started to finish. (See the Solution in Recipe 7.4 for more information on DoEvents.) Thus, the acbRunAppWait subroutine looks like this:
Public Sub acbRunAppWait(strCommand As String, intMode As Integer)
' Run an application, waiting for its completion
' before returning to the caller.
Dim hInstance As Long
Dim hProcess As Long
Dim lngRetval As Long
Dim lngExitCode As Long
On Error GoTo acbRunAppWait_Err
' Start up the application.
hInstance = Shell(strCommand, intMode)
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or SYNCHRONIZE, _
True, hInstance)
Do
' Attempt to retrieve the exit code, which will
' not exist until the application has quit.
lngRetval = GetExitCodeProcess(hProcess, lngExitCode)
DoEvents
Loop Until lngExitCode <> STILL_ACTIVE
acbRunAppWait_Exit:
Exit Sub
acbRunAppWait_Err:
Select Case Err.Number
Case acbcErrFileNotFound
MsgBox "Unable to find '" & strCommand & "'"
Case Else
MsgBox Err.Description
End Select
Resume acbRunAppWait_Exit
End Sub
To use the Shell command, you must specify an executable file. If you need to run a DOS internal command or redirect the output from a program to a text file, you'll need to load a copy of COMMAND.COM to do your work. In addition, you'll need to use the /C switch, indicating to COMMAND.COM that you just want a temporary instance that should quit when the program you run finishes. For example, to run the CHKDSK.EXE program directly, you could use the following function call (all these examples assume that the necessary programs are available in the DOS PATH):
hInstance = Shell("CHKDSK.EXE", vbMinimizedNoFocus)
To run DIR, on the other hand, you'll need to start COMMAND.COM first:
hInstance = Shell("COMMAND.COM /C DIR C:\*.BAT", vbMinimizedNoFocus)
To redirect the output from a program to a text file, you'll also need to use COMMAND.COM:
hInstance = Shell("COMMAND.COM /C CHKDSK C: > C:\ACBTEST.TXT", _
vbMinimizedNoFocus)
TIP
You may also want to study the FileRead subroutine in the sample form's module, which demonstrates how to open a text file and read its contents directly into a control on a form.
11.6. Exit Windows Under Program Control
Problem
You'd like to be able to control what happens once you quit your applications: you may want to shut down Windows at the same time, or perhaps even reboot the machine. How can you do that from within Access?
Solution
The Windows API provides an ExitWindowsEx function that grants you control over exiting Windows, and you have a choice of three different things you can do: log off and await a new login; shut down to the point at which it's safe to turn off the computer's power; or reboot the computer. This solution demonstrates these simple functions.
To try closing Windows under program control, load and run frmExitWindows from 11-06.MDB. This sample form, shown in Figure 11-7, allows you to choose from the three options. Make your choice and click on the Go button, which will execute the code necessary to quit in the manner you've specified.
Figure 11-7. frmExitWindows presents three options
To use this functionality within your own applications, follow these steps:
Import the module basExitWindows from 11-06.MDB.
Call the function from Table 11-4 that best suits your needs. In each case, if the function returns at all, it indicates that some Windows process wasn't able to shut down and that your function call failed. This won't happen often.
For example, to reboot your computer:
intRetval = acbReboot( )
Table 11-4. Available functions for exiting Windows
Function
Description
acbLogOff
Shuts down all processes running in the security context of the process that called the function, then logs off the user. Depending on the operating system, you may