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.
你可以調用'TerminateProcess()'並完成它! –
我不行。要求是用WM_CLOSE冷靜地關閉它。 – Wodzu
這似乎不工作!當它失敗時,應用程序是否顯示任何UI? –