正常结束由Shell所调用的Window 程序 来源:cww 我们曾在使"Shell指令具Wait功能"的文章中 提过,使用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来强迫中断程序。 以下程序在.BAS
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
|
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
|