0

I have the following code to demonstrate the problem. A handler treating ctrl-C (CTRL_C_EVENT) and window-close (CTRL_CLOSE_EVENT) is installed. After outputting something about the possible actions, an infinite loop is started, waiting for a user to either control-C or close the console window. In both cases a message box with a yes/no choice is given. For the ctrl-C this works fine, but clicking no when closing has no effect. Worse, after 5 seconds the whole thing is shut down anyway. This is quite according to docs, so my question is: Is there an alternative that will allow me to return to the application, rather than having 5 seconds to say my prayers and getting shot anyway? The code:

#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "user32.lib")

BOOL myCtrlHandler(DWORD fdwCtrlType)
{
    auto userwantstoquit = [](HWND wnd = nullptr)
    {
        return MessageBox(
            wnd,
            "Do you really want to stop?",
            "CTRL tester",
            MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2 | MB_APPLMODAL
        ) == IDYES;
    };
    switch (fdwCtrlType)
    {
    case CTRL_C_EVENT:
        // Console window handle is passed to prevent window interaction
        // return TRUE will stop the signal, allow app to go on
        // return FALSE will allow the other handlers to be called.
        return !userwantstoquit(GetConsoleWindow());
    case CTRL_CLOSE_EVENT:
        // passing console window handle will not display the box
        return !userwantstoquit();
    default:
        // use default handlers for everything else
        return FALSE;
    }
}

int main()
{
    SetConsoleCtrlHandler(myCtrlHandler, TRUE);
    puts("Press ctrl-C or close the console window using x");
    while (true);
    return 0;
}

MS docs say that in case of a CTRL-CLOSE signal any number of (console) cleanup routines already may have executed, so at this stage there is no way back. Possibly, then, trying to add a windows message pump is the only potential solution, but that obviously smacks of overkill for a console app. But it may be the only way to go, also, since by using MessageBox (user32.dll), there will not be CTRL_LOGOFF or CTRL_SHUTDOWN events through the CtrlHandler function.

Jan
  • 447
  • 6
  • 8
  • 1
    Your program isn't in control of the console window so there's really not much you can do. – Some programmer dude Oct 30 '19 at 12:35
  • 1
    The console host (conhost.exe) sends this event by having the session server (csrss.exe) inject a new thread in your process. For the ctrl+close event, the server waits on this thread for 5 seconds (default) before terminating the process. There is no way out of this; the process must die. If you need your application to continue running after the console is closed, create a client/server architecture with a backend server process that's not attached to the console. Then if the UI client is killed, you can respawn it with a new console. – Eryk Sun Oct 30 '19 at 18:01
  • @Someprogrammerdude I suppose you are right. I was going to investigate a notion of a hidden window to get the messages earlier, see https://stackoverflow.com/questions/2122506/how-to-create-a-hidden-window-in-c. But it appears tenuous, though not difficult. – Jan Oct 30 '19 at 20:40
  • @ErykSun I'll delve into that, haven't got that much experience, but there are examples, so I'll give it a try. thanks. – Jan Oct 30 '19 at 20:41

0 Answers0