我有进程的ID。这个过程是一个有一个主窗口的应用程序。我正在尝试通过将 WM_CLOSE 发送到其主窗口来关闭此应用程序。我正在使用搜索其主窗口EnumWindows
。
问题是,我尝试关闭的这个应用程序并不总是关闭。它是多线程应用程序。当我使用下面介绍的相同方法时,记事本和 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.