Можно ли отправлять сообщения WM_QUERYENDSESSION в окно в другом процессе?
Вопрос
Я хочу отладить приложение для Windows C ++, которое я написал, чтобы понять, почему оно не отвечает на WM_QUERYENDSESSION так, как я ожидаю.Очевидно, что сделать это, просто выключив систему, немного сложно.Есть ли какая-нибудь утилита или код, который я могу использовать, чтобы самостоятельно отправить поддельную WM_QUERYENDSESSION в Windows моего приложения?
Решение
Я использовал Win32::GuiTest Модуль Perl для выполнения подобных действий в прошлом.
Другие советы
Для этого можно использовать Windows API SendMessage.http://msdn.microsoft.com/en-us/library/ms644950 (ПРОТИВ 85).aspx
Возможно ли, что он не отвечает, потому что какой-то другой запущенный процесс ответил нулем (заставляя систему ждать этого)?
Да, конечно, это возможно.Я столкнулся с подобной проблемой несколько месяцев назад, когда какое-то (неизвестное, но, вероятно, мое) приложение предотвращало завершение работы, поэтому я написал быстрый код, который использовал EnumWindows для перечисления всех окон верхнего уровня, отправил каждому сообщение WM_QUERYENDSESSION, отметил, каким было возвращаемое значение из SendMessage, и остановил перечисление, если кто-либо вернул FALSE.Потребовалось около десяти минут на C ++ / MFC.В этом и заключалась суть дела:
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);
if (csTitle.GetLength() == 0)
{
GetWindowThreadProcessId (hTarget, &dwPID);
csTitle.Format ("<PID=%d>", dwPID);
}
if (pWnd->SendMessage (WM_QUERYENDSESSION, 0, ENDSESSION_LOGOFF))
{
csMsg.Format ("window 0x%X (%s) returned TRUE", hTarget, csTitle);
}
else
{
csMsg.Format ("window 0x%X (%s) returned FALSE", hTarget, csTitle);
bRetVal = FALSE;
}
mg_pThis->m_ctrl_ListMsgs.AddString (csMsg);
}
else
{
csMsg.Format ("Unable to resolve HWND 0x%X to a CWnd", hTarget);
mg_pThis->m_ctrl_ListMsgs.AddString (csMsg);
}
return bRetVal;
}
mg_pThis был просто локальной копией этого указателя диалогового окна, поэтому вспомогательный обратный вызов мог получить к нему доступ.Я же говорил тебе, что это было быстро и грязно :-)
ДА.Если вы можете получить дескриптор окна (возможно, используя FindWindow()), вы можете отправить / опубликовать любое сообщение в нем, если WPARAM & LPARAM не являются указателями.