windows – 如何找到阻止关机的HWND?

前端之家收集整理的这篇文章主要介绍了windows – 如何找到阻止关机的HWND?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的应用程序中的某个地方(以及第三方代码库)是一个阻止 Windows的窗口过程:

>退出
>关闭
>重新启动

我在我的代码中找到了一个位置,我在调用DefWindowProc时犯了一个非常常见的错误,但调用错误

FBroadcastListenerHwnd := AllocateHWnd(BroadcastListenerWindowProc);

procedure TGrobber.BroadcastListenerWindowProc(var msg: TMessage);
begin
   DefWindowProc(FBroadcastListenerHwnd,msg.msg,msg.wparam,msg.lparam);
end;

我修复了那个bug,而我的test program不再停止关机了.

但完整的应用程序

我现在面临着不得不撕掉一个程序,直到我的计算机终于重新启动.

在我的应用程序内部的某个地方是一个附加到HWND的Window过程,它返回零到WM_QUERYENDSESSION.如果我只知道HWND,我可以使用Spy找到Window.

但我怎么能找到那个人呢?

Windows应用程序事件日志记录了停止关闭的过程:

并且在更详细的应用程序和服务日志中有更详细的日志.但那些没有证件.

我怎样才能找到有问题的hwnd?

尝试

我尝试使用EnumThreadWindows来获取我的“主”线程的所有窗口,并想要手动向它们发送WM_QUERYENDSESSION以查看谁返回false:

var
   wnds: TList<HWND>;

function DoFindWindow(Window: HWnd; Param: LPARAM): Bool; stdcall;
var
   wnds: TList<HWND>;
begin
   wnds := TList<HWND>(Param);
   wnds.Add(Window);
   Result := True;
end;

wnds := TList<HWND>.Create;
enumProc := @DoFindWindow;
EnumThreadWindows(GetCurrentThreadId,EnumProc,LPARAM(wnds));

现在我列出了12个hwnds.戳他们:

var
   window: HWND;
   res: LRESULT;

for window in wnds do
begin
    res := SendMessage(window,WM_QUERYENDSESSION,0);
    if res = 0 then
    begin
        ShowMessage('Window: '+IntToHex(window,8)+' returned false to WM_QUERYENDSESSION');
    end;
end;

但没有人确实归零.

所以这是排水管的一个管.

EnumThreadWindows只枚举一个特定线程的窗口.可能是在一个线程中创建了违规窗口.因此,我建议您使用EnumWindows在您的应用程序中枚举所有顶级窗口以进行测试.

它足以在一个线程中初始化COM,你将拥有一个你不知道的窗口.这样在线程中调用WaitForSingleObject可能是你的罪魁祸首:
Debugging an application that would not behave with WM_QUERYENDSESSION

猜你在找的Windows相关文章