我的应用程序中的某个地方(以及第三方代码库)是一个阻止
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