|
提過,使用TerminateProcess()來結束一個由Shell所引發的Process,但也說過,這可
能會有一些問題,如果說,所引發的是一般正常且單一的Window程式(如NotePad),那
是有辦法令之正常結束的,那便是使用PostMessage(hWnd, WM_CLOSE,0,0),令該Window
結束。然而,Shell的傳回值是Process ID而不是hWnd,所以要加一些動作來取得hWnd。
我們可以用 GetForegroundWindow來做(如果該Shell是指定vbNormalFocus),另也可以使
用FindWindow來做,但是,如果有兩個NotePad在時,會取到那一個,實在不知。另外使
EnumWindows來做,該Function用來巡行Top Level的Window,我們傳入ProcessID當做
EnumWindows的第二個參數,於是EnumWindowProcedure中的lParam便是該ProcessID,我
們另外用tid = GetWindowThreadProcessId(hwnd, pid)來取得hWnd所屬的ProcessID
與我們傳入的ProcessID(lParam)做比較,若相同,代表我們已找到所要的hWnd了。
EnumWindows的用法請參考嘗試尋找電腦中執行的程式
當然,這個程式的做法不是萬能的,如果產生的Process又產生有好多個Window,我們結束
的,可能只是其中之一,那程式可能要改一下,變成只要在EnumWindow Procedure中找到
一個PID與Shell傳回值的PID相同者,就使用PostMessage(hwnd, WM_CLOSE, 0,0)來結束
之,但這也不一定就全然可行,如果產生的不是一個有Window的程式,那使用WM_CLOSE
是沒有用的,唯一能做的,就是使用TerminateProcess來強迫中斷程式。
Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Declare Function SetForegroundWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hwnd As Long) As Long
Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Declare Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, lpExitCode As Long) As Long
Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long
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
Public Const SYNCHRONIZE = &H100000
Public Const STILL_ALIVE = &H103
Public Const INFINITE = &HFFFF
Public Const WM_CLOSE = &H10
Public hWnd5 As Long
Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
Dim S As String
If GetParent(hwnd) = 0 Then
Dim tid As Long, pid As Long
tid = GetWindowThreadProcessId(hwnd, pid)
If pid = lParam Then
hWnd5 = hwnd
EnumWindowsProc = False
End If
End If
EnumWindowsProc = True ' 表示繼續列舉 hWnd
End Function
以下程式在Form
Option Explicit
Private ExitCode As Long
Private hProcess As Long
Private isDone As Long
Private Sub Command1_Click()
Dim pid As Long
pid = Shell("notepad.exe", vbNormalFocus)
Call EnumWindows(AddressOf EnumWindowsProc, pid) '設定hWnd5的值
hProcess = OpenProcess(SYNCHRONIZE , 0, pid)
isDone = False
Do
Call GetExitCodeProcess(hProcess, ExitCode)
DoEvents
Loop While ExitCode = STILL_ALIVE Or isDone
Call CloseHandle(hProcess)
isDone = True
Label1.Caption = "Over"
End Sub
Private Sub Command2_Click()
Dim i As Long
Call SetForegroundWindow(hWnd5)
Call PostMessage(hWnd5, WM_CLOSE, 0, 0)
End Sub
Private Sub Form_Unload(Cancel As Integer)
isDone = True
End Sub |
|