Normal Termination of an external program using VB6
I know how to close external programs using TerminateProcess API Function and ExitProcess API Function and Tskkill DOS Command but i need to find a way to close opened programs normally...
Something like clicking on close button of programs...
Can anyone help me?
tnx :wave:
Re: Normal Termination of an external program using VB6
PostMessage the WM_CLOSE message to that window. BTW, it's a good thing you've decided to gracefully close other processes because terminating them abruptly may lead to memory leaks. The MS KB article How To Terminate an Application "Cleanly" in Win32 outlines the steps you need to take.
Re: Normal Termination of an external program using VB6
Quote:
Originally Posted by
Bonnie West
the PostMessage function is g8. tnx a lot :)
but the PostMessage is unable to close applications by (file name example: test.exe) it can close (visible) applications by their (title name=caption) :(
Re: Normal Termination of an external program using VB6
Code:
Option Explicit 'In a standard module
Option Compare Text 'Enable case-insensitive string comparisons for the Like operator
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetProcessImageFileNameW Lib "psapi.dll" (ByVal hProcess As Long, ByVal lpImageFileName As Long, ByVal nSize As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, Optional ByRef lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function SendMessageTimeoutW Lib "user32.dll" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal fuFlags As Long, ByVal uTimeout As Long, Optional ByRef lpdwResult As Long) As Long
Private Declare Function SysReAllocStringLen Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32.dll" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
'This subroutine attempts to terminate a process gracefully.
'There are, however, some limitations: it can only close
'processes which have a top-level window and it can't kill
'certain processes like anti-virus and 64-bit processes.
'The ImageName argument accepts either a specific filename
'or a filename that includes wildcard characters like * or ?
Public Sub EndProcess(ByRef ImageName As String)
EnumWindows AddressOf EnumWindowsProc, VarPtr(ImageName)
End Sub
Private Function EnumWindowsProc(ByVal hWnd As Long, ByRef lParam As String) As Long
Const PROCESS_QUERY_INFORMATION = &H400&, PROCESS_TERMINATE = &H1&
Const BUFFER_SIZE = 300&, SMTO_ABORTIFHUNG = &H2&, WM_CLOSE = &H10&, TIMEOUT = 5000& '<-- 5 Secs.
Dim PID As Long, hProcess As Long, StartPos As Long, EndPos As Long, sBuffer As String
If GetWindowThreadProcessId(hWnd, PID) Then
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_TERMINATE, 0&, PID)
If hProcess Then
SysReAllocStringLen VarPtr(sBuffer), , BUFFER_SIZE
EndPos = GetProcessImageFileNameW(hProcess, StrPtr(sBuffer), BUFFER_SIZE + 1&)
If EndPos Then
StartPos = InStrRev(sBuffer, "\", EndPos)
If Mid$(sBuffer, StartPos + 1&, EndPos - StartPos) Like lParam Then
If SendMessageTimeoutW(hWnd, WM_CLOSE, 0&, 0&, SMTO_ABORTIFHUNG, TIMEOUT) = 0& Then
PID = TerminateProcess(hProcess, 0&): Debug.Assert PID
End If
End If
End If
hProcess = CloseHandle(hProcess): Debug.Assert hProcess
End If
End If
EnumWindowsProc = 1&
End Function
Code:
EndProcess "calc.exe"
EndProcess "notepad.???"
EndProcess "Project*"
Re: Normal Termination of an external program using VB6
Quote:
Originally Posted by
Bonnie West
Code:
Option Explicit 'In a standard module
Option Compare Text 'Enable case-insensitive string comparisons for the Like operator
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetProcessImageFileNameW Lib "psapi.dll" (ByVal hProcess As Long, ByVal lpImageFileName As Long, ByVal nSize As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, Optional ByRef lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function SendMessageTimeoutW Lib "user32.dll" (ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal fuFlags As Long, ByVal uTimeout As Long, Optional ByRef lpdwResult As Long) As Long
Private Declare Function SysReAllocStringLen Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32.dll" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
'This subroutine attempts to terminate a process gracefully.
'There are, however, some limitations: it can only close
'processes which have a top-level window and it can't kill
'certain processes like anti-virus and 64-bit processes.
'The ImageName argument accepts either a specific filename
'or a filename that includes wildcard characters like * or ?
Public Sub EndProcess(ByRef ImageName As String)
EnumWindows AddressOf EnumWindowsProc, VarPtr(ImageName)
End Sub
Private Function EnumWindowsProc(ByVal hWnd As Long, ByRef lParam As String) As Long
Const PROCESS_QUERY_INFORMATION = &H400&, PROCESS_TERMINATE = &H1&
Const BUFFER_SIZE = 300&, SMTO_ABORTIFHUNG = &H2&, WM_CLOSE = &H10&, TIMEOUT = 5000& '<-- 5 Secs.
Dim PID As Long, hProcess As Long, StartPos As Long, EndPos As Long, sBuffer As String
If GetWindowThreadProcessId(hWnd, PID) Then
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_TERMINATE, 0&, PID)
If hProcess Then
SysReAllocStringLen VarPtr(sBuffer), , BUFFER_SIZE
EndPos = GetProcessImageFileNameW(hProcess, StrPtr(sBuffer), BUFFER_SIZE + 1&)
If EndPos Then
StartPos = InStrRev(sBuffer, "\", EndPos)
If Mid$(sBuffer, StartPos + 1&, EndPos - StartPos) Like lParam Then
If SendMessageTimeoutW(hWnd, WM_CLOSE, 0&, 0&, SMTO_ABORTIFHUNG, TIMEOUT) = 0& Then
PID = TerminateProcess(hProcess, 0&): Debug.Assert PID
End If
End If
End If
hProcess = CloseHandle(hProcess): Debug.Assert hProcess
End If
End If
EnumWindowsProc = 1&
End Function
Code:
EndProcess "calc.exe"
EndProcess "notepad.???"
EndProcess "Project*"
Your code worked g8... tnx a lot
but there is problem...
do you know WAMPSERVER?
i have 32 bit version of it.
when i do right click on the (system try icon) of it and click (Exit)... the WAMP SERVER program will try to close (itself) + (all hidden opened programs related to the wamp... like: httpd.exe and etc...)
but your code will try to close wampmanager.exe only
yes tried to close wampmanager.exe in safe mode, but it couldn't execute (Exit) command in WAMP SERVER program.
i have a suggestion... if we do convert hProcess to hwnd, we can use PostMessage function for this. but i don't know how to convert it :( hProcess is an argument of TerminateProcess function:
Code:
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
Declare Function TerminateProcess Lib "kernel32" Alias "TerminateProcess" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Re: Normal Termination of an external program using VB6
Quote:
Originally Posted by
Mehdi Jazini
do you know WAMPSERVER?
No.
Quote:
Originally Posted by
Mehdi Jazini
i have 32 bit version of it.
when i do right click on the (system try icon) of it and click (Exit)... the WAMP SERVER program will try to close (itself) + (all hidden opened programs related to the wamp... like: httpd.exe and etc...)
but your code will try to close wampmanager.exe only
yes tried to close wampmanager.exe in safe mode, but it couldn't execute (Exit) command in WAMP SERVER program.
In your OP, you failed to mention that you wanted to terminate the child processes too. I had no way of knowing what you really required, hence the code in post #4 didn't take that into account. In order to prevent further confusion, can you please describe your requirements in utmost detail? Thank you. (When composing an OP, you should always divulge as much information as possible about the problem.)
Quote:
Originally Posted by
Mehdi Jazini
i have a suggestion... if we do convert hProcess to hwnd, we can use PostMessage function for this. but i don't know how to convert it :( hProcess is an argument of TerminateProcess function:
In the code above, I've replaced the PostMessage function with the SendMessageTimeout function so that the code will wait a certain amount of time for the WM_CLOSE message to be processed by the target window. This synchronous approach simplifies the code a bit by eliminating the WaitForSingleObject function.
Here's what the code above does:
- All the top-level windows (those that are neither a child control nor owned window) are enumerated.
- Each window's Process ID is obtained so that its process can be opened.
- The fully-qualified pathname of the process is retrieved and the filename component is extracted.
- The process' filename is compared (using the Like operator) against the specified ImageName.
- If the names match, the current window is requested to close via the WM_CLOSE message.
- If the window failed to close within the designated time limit, the code then attempts to forcibly terminate the window's process.
- Steps 2-6 are repeated for the other windows whose processes matches the specified ImageName, if any.
Are you saying you want to do the reverse? That is, enumerate the windows of a given process? Well, it can be done through the CreateToolhelp32Snapshot, Thread32First, Thread32Next and EnumThreadWindows functions.