2011-08-02 1 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で見てください。あなたはこれまでのところそれをやっています。記事は、(あなたは1がメインである確実に知ることができないので)にあなたが

  • 最初のポストWM_CLOSEアプリケーションのすべての窓ことを示唆しています。
  • 経過タイムアウトタイムアウトとしている場合、待機
  • は、私は同意するのTerminateProcess

を使用してアプリケーションを殺します。

関連する問題