确定哪个应用程序阻止了关机

4
与Windows Vista不同,当Windows XP关闭时,它不会告诉你哪个程序请求不要关闭。这导致Windows仍在运行,而且没有告诉你哪个程序阻止了关机。
据我所知,Windows向所有应用程序发送WM_QUERYENDSESSION。如果任何一个应用程序将0返回给该函数,则关机会停止。
我想知道是否有一种方法可以捕获程序的返回值并确定为什么Windows XP无法关闭。
谢谢 Phil

鸡生蛋蛋生鸡的问题。任何试图查找阻止关闭进程的程序本身都会阻止关闭。 - Hans Passant
2个回答

3

枚举所有顶级窗口(使用EnumWindows()),并向每个窗口发送WM_QUERYENDSESSION消息。对于返回阻止值的窗口,检测它所属的进程。要执行后者,请调用GetWindowThreadProcessId(),枚举所有进程,并找到具有该ID的进程。


1

是的。我在这个问题中发布了代码,但这是代码的改进版本:

void CQes_testDlg::OnBtnTest()  
{  
   // enumerate all the top-level windows.  
   m_ctrl_ListMsgs.ResetContent();  
   EnumWindows (EnumProc, 0);  
}  

BOOL CALLBACK EnumProc (HWND hTarget, LPARAM lParam)
{
   CString csTitle;
   CString csMsg;
   CWnd *  pWnd = CWnd::FromHandle (hTarget);
   BOOL    bRetVal = TRUE;
   DWORD   dwPID;

   if (pWnd)
      pWnd->GetWindowText (csTitle);
   else
      csTitle = TEXT("<unknown>");

   GetWindowThreadProcessId (hTarget, &dwPID);

   if (pWnd->SendMessage (WM_QUERYENDSESSION, 0, ENDSESSION_LOGOFF))
   {
      csMsg.Format ("window 0x%X (PID=%d, Title='%s') returned TRUE", 
                    hTarget, dwPID, csTitle);
   }
   else
   {
      csMsg.Format ("window 0x%X (PID=%d, Title='%s') returned FALSE *******", 
                    hTarget, dwPID, csTitle);
      bRetVal = FALSE;
   }

   mg_pThis->m_ctrl_ListMsgs.AddString (csMsg);
   return bRetVal;
}

mg_p是指向对话框对象的模块全局指针,因此枚举器可以访问它的控件。


请注意,每个 WM_QUERYENDSESSION 必须跟随一个 WM_ENDSESSION(在这种情况下,表示“会话未结束”)。 - Raymond Chen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接