新聞| | PChome| 登入
2007-10-25 23:54:15 | 人氣96| 回應0 | 上一篇 | 下一篇
推薦 0 收藏 0 轉貼0 訂閱站台

正常結束由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
以下程式在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

                                                        

台長: Kenny
人氣(96) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: 程式設計 |
此分類下一篇:SHELL具WAIT功能
此分類上一篇:如何自動移動Mouse

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文