は(Windows 7の上で実行されている)私は、コンソールアプリケーションで何をすべきかです:
私。閉じる/ログオフ通知を待つための隠しウィンドウを作成します。重要:
void interrupt::start()
{
WNDCLASSEX wc = {};
HINSTANCE hi = GetModuleHandle(NULL);
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
// . . . etc
if(!RegisterClassEx(&wc))
return;
hwnd_ = CreateWindowEx(WS_EX_CLIENTEDGE, class_name, "Waiting for user logoff event",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hi , NULL);
ShowWindow(hwnd_, SW_HIDE);
UpdateWindow(hwnd_);
MSG msg = {};
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// call internal function for sending "stop" notification to rest of program
ctrl.stop(CTRL_CLOSE_EVENT);
}
IIそのメッセージループのためにそれを自身のスレッドを与えます。ウィンドウメッセージハンドラで "特別なイベント"の処理を実装する
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_ENDSESSION:
if (lParam)
{
// call internal function for sending "stop" notification to rest of program
ctrl.stop(lParam == ENDSESSION_LOGOFF ? (int) interrupt::logoff : CTRL_CLOSE_EVENT);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
iii。 「停止」要求を処理するための内部機能を実装する。 2つの特別な条件を処理する必要があります。
a。 がウィンドウメッセージスレッドから呼び出された場合、ウィンドウにWM_CLOSEを送信し、スレッドが終了するまで待ちます。
b。 がでメインスレッドから呼び出された場合は、静的変数の終了(少なくとも1つ)を待ちます。
これは、CtrlHandlerの終了後、Windowsが無条件でプロセスを終了させ、コードをクリーンアップすることがないためです。静的変数はメインスレッドで破棄されるため、この待機は少なくともint main()
が終了したことを保証します。静的変数のコンストラクタ(メインウィンドウの "shadow"ウィンドウを開始したものと同じもの)のメインスレッドのスレッドIDを取得できます。ここで
は、私は私のコードでそれをやった方法です:
void interrupt::stop(int signal)
{
// . . .
// Set exit signal
InterlockedExchange(&stage_, 2L);
// Close shadow window if notification is from elsewhere
if (hwnd_ && GetCurrentThreadId() != thread_.id())
{
PostMessage(hwnd_, WM_CLOSE, 0, 0);
thread_.wait();
}
// Wait for completion of own destructor on main thread
if (GetCurrentThreadId() != main_thread_id_)
while(stage_ != 3L)
Sleep(10);
}
// My static variable to wait for
interrupt ctrl;
うん、この動作はVistaで変更されました。プログラムでシャットダウンをブロックすることはできません。 –
これ以上の通知はありませんか?このように閉じたときにプロセスがクリーンアップを実行することは可能ですか? –
はい、Vista(Server 2008)ではこれが変更されています。ログオフイベントはもう受信しません。私自身のコンソールアプリケーションのために、私は隠されたウィンドウを作成し、クローズイベントとログオフイベントの両方を受け取ります。 – bronekk