MORE INFORMATION
To programmatically close a single instance of a Windows program, use the
FindWindow function to get the handle to the window that you want to close. The
FindWindow function returns the handle of a top-level window with a class name and a window name that match the string parameters. The
FindWindow function returns the handle of the window as a long value if it is successful, and it returns the handle of the window as a null value if it fails. To use
FindWindow, you must supply the following two parameters:
- lpClassName - a pointer to a null-terminated string that specifies the class name
-or-
a null-terminated string that is an atom that identifies the class-name string.
In this program, you can pass vbNullString. - lpWindowName - a pointer to a null-terminated string that specifies the window name (the title of the window).
Use the handle to send a message to close the window with the
PostMessage
function. The
PostMessage function sends a message to a program message
queue, which returns a value immediately. This function returns a non-zero
value if it is successful, and it returns a zero value if it fails.
To use the
PostMessage function, you must specify the following four parameters:
- hWnd - the handle of the window that you want to close.
This long value is available as the result of the FindWindow function. - uInt - the message to post to the message queue. In this program, use the WM_CLOSE message.
- wParam - the first message parameter. For this message, pass a null value.
- lParam - the second message parameter. For this message, pass a null value.
If you send a message too soon in the event, a synchronization problem may occur that causes the program to quit before the message is processed. When you use the
WaitForSingleObject function, this makes sure that the message is processed before the program quits.
To use the
WaitForSingleObject function, you must specify the following two parameters:
- hHandle - the handle of the object that you want to monitor.
- dwMilliseconds - specifies the time-out interval in milliseconds.
If you set this parameter to infinite, the time-out interval of the function never elapses.
The
WaitForSingleObject function requires a process handle, which is different from an
hWnd. You must call
GetWindowThreadProcessId to determine the ProcessID, and then pass it to the
OpenProcess function to obtain a process handle.
To make sure that the program is closed, use the
IsWindow function to determine whether the handle is valid. The
IsWindow function returns a non-zero value if the handle is valid, and it returns a zero value if the handle does not exist.
To use the
IsWindow function, specify the handle to check. If the handle still exists, you can use the
TerminateProcess function to stop the handle process. However, Microsoft does not recommended that you use this extreme approach. Although you may have stopped the handle process, the dynamic-link libraries (DLLs) that are used by the handle may still reside in memory, which causes a memory leak. Use the
TerminateProcess function with caution.
Create the Sample Program
This section describes how to create a sample program that shows you how to use Visual Basic code to quit a running program. The sample program
starts and stops the Windows Calculator program.
To create the sample program, follow these steps:
- Start a new Standard EXE project in Visual Basic. By default, Form1 is created.
- Add two CommandButton controls to Form1.
- Copy the following code to the Code window of Form1:
Option Explicit
Private Declare Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" _
Alias "PostMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Declare Function IsWindow Lib "user32" _
(ByVal hwnd As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, _
lpdwProcessId As Long) As Long
'Constants that are used by the API
Const WM_CLOSE = &H10
Const INFINITE = &HFFFFFFFF
Const SYNCHRONIZE = &H100000
Private Sub Form_Load()
Command1.Caption = "Start the Calculator"
Command2.Caption = "Close the Calculator"
End Sub
Private Sub Command1_Click()
'Starts Windows Calculator
Shell "calc.exe", vbNormalNoFocus
End Sub
Private Sub Command2_Click()
'Closes Windows Calculator
Dim hWindow As Long
Dim hThread As Long
Dim hProcess As Long
Dim lProcessId As Long
Dim lngResult As Long
Dim lngReturnValue As Long
hWindow = FindWindow(vbNullString, "Calculator")
hThread = GetWindowThreadProcessId(hWindow, lProcessId)
hProcess = OpenProcess(SYNCHRONIZE, 0&, lProcessId)
lngReturnValue = PostMessage(hWindow, WM_CLOSE, 0&, 0&)
lngResult = WaitForSingleObject(hProcess, INFINITE)
'Does the handle still exist?
DoEvents
hWindow = FindWindow(vbNullString, "Calculator")
If IsWindow(hWindow) = 1 Then
'The handle still exists. Use the TerminateProcess function
'to close all related processes to this handle. See the
'article for more information.
MsgBox "Handle still exists."
Else
'Handle does not exist.
MsgBox "All Program Instances Closed."
End If
End Sub
- Press F5 to run the program.
- To start the Windows Calculator program, click Start the Calculator.
To quit the Windows Calculator program, click Close the Calculator.
REFERENCES
For additional information, click the article numbers below
to view the articles in the Microsoft Knowledge Base:
129797 How To Launch a Win32 Application from Visual Basic
129796 How To Use a 32-Bit Application to Determine When a Shelled Process Ends
For additional information, see both of the following:
- Platform SDK documentation on FindWindow and PostMessage functions
- Visual Basic 5.0 Programmer's Guide to the Win32 API