2011-08-02 38 views
1

我有進程的ID。這個過程是一個有主窗口的應用程序。 我想通過發送WM_CLOSE到它的主窗口來關閉這個應用程序。 我正在使用EnumWindows正在搜索其主窗口。只有進程ID時關閉主應用程序窗口的問題

問題是,我嘗試關閉的這個應用程序並不總是關閉。 它是多線程應用程序。當我使用下面介紹的相同方法時,記事本和Calc始終關閉。但我不確定它是否正常工作,因爲它會將多個句柄返回到同一個窗口,即使對於Calc.exe也是如此。

是否有可能線程正在處理窗口,然後這個句柄以某種方式被破壞?或者,也許我不應該使用GetWindowThreadProcessId(hHwnd,pPid),但在回調中的一些其他功能?

我沒有想法,會感激任何幫助。謝謝。

代碼片段:

unit Unit22; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    TForm22 = class(TForm) 
    edtprocID: TEdit; 
    lblEnterProcessID: TLabel; 
    btnCloseProcessWindow: TButton; 
    lblStatus: TLabel; 
    procedure btnCloseProcessWindowClick(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

type 
    THandleAndHWND = record 
    ProcID: THandle; 
    WindowHandle: HWND; 
    end; 

var 
    Form22: TForm22; 

var 
    HandleAndHWNDArray: array of THandleAndHWND; 
    HandeIndex, lp: Integer; 

implementation 

{$R *.dfm} 

function EnumProcess(hHwnd: HWND; lParam : integer): boolean; stdcall; 
var 
    pPid : DWORD; 
begin 
    //if the returned value in null the 
    //callback has failed, so set to false and exit. 
    if (hHwnd=0) then 
    begin 
    result := false; 
    end else 
    begin 
    GetWindowThreadProcessId(hHwnd,pPid); 
    Inc(HandeIndex); 
    HandleAndHWNDArray[HandeIndex].ProcID := pPid; 
    HandleAndHWNDArray[HandeIndex].WindowHandle := hHwnd; 
    Result := true; 
    end; 

end; 

procedure TForm22.btnCloseProcessWindowClick(Sender: TObject); 
var 
    ProcID: Cardinal; 
    i, LastError: Integer; 
begin 
    HandeIndex := -1; 
    ProcID := StrToInt(edtprocID.Text); 

    SetLength(HandleAndHWNDArray, 3000); 
    EnumWindows(@EnumProcess,lp); 

    for i := 0 to HandeIndex do //After EnumWindows HandleIndex is above 500 despite the fact that I have like 10 openned windows max 
    begin      //That means that EnumWindows was called 500 times? 
    if HandleAndHWNDArray[i].ProcID = ProcID then //search for process equal to procces ID given by the user 
    begin 
     //if we have a processID then we have a handle to its main window 
     if PostMessage(HandleAndHWNDArray[i].WindowHandle, WM_CLOSE, 0, 0) then 
     begin 
     lblStatus.Caption := 'message posted!'; 
     end else 
     begin 
     LastError := GetLastError; 
     lblStatus.Caption := Format('Error: [%d] ' + SysErrorMessage(LastError), [LastError]); 
     end; 
     Exit; 
    end; 
    end; 

end; 

end. 
+1

你可以調用'TerminateProcess()'並完成它! –

+0

我不行。要求是用WM_CLOSE冷靜地關閉它。 – Wodzu

+0

這似乎不工作!當它失敗時,應用程序是否顯示任何UI? –

回答

3

對如何儘可能乾淨關閉另一個應用程序在此知識庫文章here看看。你到目前爲止做得很對。文章建議,你

  • 的第一篇文章WM_CLOSE到應用程序的所有窗口(因爲你不能肯定知道哪一個是主要的)。
  • 等待以超時,如果超時時間
  • 殺死使用了TerminateProcess

我同意申請。

相關問題