ページ 11

C++CUIでSetConsoleCtrlHandlerを使いたい

Posted: 2018年11月05日(月) 22:37
by DAICHI0922
C++で以下のプログラムを書いたのですが、シグナル発生時に関数を呼び出し、Sleepさせても数秒は耐えるのですが、指定した秒数は待ってはくれません。どうにかならないでしょうか?

MessageBoxでは、いいえを選択した場合シャットダウンを中止させたいのですが...。

コード:

#include <stdio.h>
#include <windows.h>
#include <thread>
#include <iostream>
using namespace std;

BOOL WINAPI controlHandler(DWORD type)
{
if (CTRL_C_EVENT == type) {
cout << "Ctrl+C" << endl;
Sleep(30000);
}
if (CTRL_CLOSE_EVENT == type) {
cout << "CLOSE" << endl;
Sleep(30000);
}
if (CTRL_LOGOFF_EVENT == type) {
cout << "LOGOFF" << endl;
Sleep(30000);
}
if (CTRL_SHUTDOWN_EVENT == type) {
cout << "SHUTDOWN" << endl;
HWND hwnd = GetConsoleWindow();
MessageBox(hwnd,"シャットダウンしますか?","",MB_OKCANCEL);
system("shutdown /a");
Sleep(30000);
}
return TRUE;
}

int main()
{
printf("main[%d] start\n", GetCurrentProcessId());

if (!SetConsoleCtrlHandler(controlHandler, TRUE)) {
printf("SetConsoleCtrlHandler");
return -1;
}

for (;;);

printf("main[%d] end\n", GetCurrentProcessId());

return 0;
}

Re: C++CUIでSetConsoleCtrlHandlerを使いたい

Posted: 2018年11月07日(水) 23:32
by YuO
DAICHI0922 さんが書きました:
6年前
MessageBoxでは、いいえを選択した場合シャットダウンを中止させたいのですが...。
できません。
それどころか,MessageBox functionの使用はuser32.dllを読み込むため,
docsの通りならCTRL_LOGOFF_EVENTやCTRL_SHUTDOWN_EVENTが送られなくなります。

APIのマニュアルであるSetConsoleCtrlHandler functionや,
ハンドラのマニュアルであるHandlerRoutine callback functionを読むと,
CTRL_CLOSE_EVENT/CTRL_LOGOFF_EVENT/CTRL_SHUTDOWN_EVENTは該当の標準動作をキャンセルできるわけではないことがわかります。

最後に,別の箇所,WM_QUERYENDSESSION messageから辿ると見つかる内容に関して,
反応がなかった別のスレッドでの私の回答ですが,再掲します。
YuO さんが書きました:
6年前
see) Shutdown Changes for Windows Vista | Microsoft Docs
Canceling shutdown | Note that the system does not allow console applications or applications without a visible window to cancel shutdown.
というわけで,Console ApplicationはShutdownをキャンセルできません。