Håndter CTRL+C på Win32

Håndter CTRL+C på Win32

Følgende kode virker for mig:

#include <windows.h> 
#include <stdio.h> 

BOOL WINAPI consoleHandler(DWORD signal) {

    if (signal == CTRL_C_EVENT)
        printf("Ctrl-C handled\n"); // do cleanup

    return TRUE;
}

int main()
{
    running = TRUE;
    if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
        printf("\nERROR: Could not set control handler"); 
        return 1;
    }

    while (1) { /* do work */ }

    return 0;
}

Ifølge dokumentationen, når handleren (som er erklæret forkert, BTW) modtager en CTRL_CLOSE_EVENT , CTRL_LOGOFF_EVENT eller CTRL_SHUTDOWN_EVENT signal, afsluttes processen, efter at handleren er gået ud. For at gøre, hvad du forsøger, er det meningen, at du skal flytte din oprydningskode ind i selve handleren.


Afhængigt af dine specifikke krav har du en række muligheder. Hvis du blot vil ignorere Ctrl +C du kan ringe til SetConsoleCtrlHandler bestå NULL som HandlerRoutine parameter:

int _tmain(int argc, _TCHAR* argv[])
{
    SetConsoleCtrlHandler(NULL, TRUE);

    // do work

    return 0;
}

Dette fjerner alle signalbehandlere. For at afslutte denne applikation skal du implementere brugerdefineret logik for at bestemme, hvornår du skal lukke ned.

Hvis du vil håndtere Ctrl +C du har to muligheder:Indstil en handler til signalet eller send tastaturinputtet videre til almindelig tastaturhåndtering.

Opsætning af en handler svarer til koden ovenfor, men i stedet for at sende NULL som handler sørger du for din egen implementering.

#include <windows.h>
#include <stdio.h>

volatile bool isRunnung = true;

BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) {
    switch (dwCtrlType)
    {
    case CTRL_C_EVENT:
        printf("[Ctrl]+C\n");
        isRunnung = false;
        // Signal is handled - don't pass it on to the next handler
        return TRUE;
    default:
        // Pass signal on to the next handler
        return FALSE;
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    SetConsoleCtrlHandler(HandlerRoutine, TRUE);

    printf("Starting\n");
    while ( isRunnung ) {
        Sleep(0);
    }
    printf("Ending\n");

   return 0;
}

Outputtet af denne applikation er:

Starting
[Ctrl]+C
Ending

Bemærk, at oprydningskoden udføres, uanset koden inde i hovedkoden while -løkke. Signalhandlere danner en sammenkædet liste, hvor handlerfunktionerne kaldes på en sidst registrerede, førstkaldte basis, indtil en af ​​handlerne returnerer TRUE . Hvis ingen af ​​handlerne returnerer TRUE, kaldes standardhandleren. Standardhandleren for en konsol kalder ExitProcess når du behandler Ctrl +C .

Hvis du vil forhindre enhver forbehandling og håndtere Ctrl +C som almindelig tastaturinput skal du i stedet ændre konsoltilstanden ved at ringe til SetConsoleMode .

#include <windows.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwMode = 0x0;
    GetConsoleMode( GetStdHandle(STD_INPUT_HANDLE), &dwMode );
    // Remove ENABLE_PROCESSED_INPUT flag
    dwMode &= ~ENABLE_PROCESSED_INPUT;
    SetConsoleMode( GetStdHandle(STD_INPUT_HANDLE), dwMode );

    while ( true ) {
        // Ctrl+C can be read using ReadConsoleInput, etc.
    }

    return 0;
}

Når ENABLE_PROCESSED_INPUT flag er fjernet Ctrl +C behandles ikke længere af systemet og sendes til konsollen som almindelig tastaturinput. Den kan læses ved hjælp af ReadConsoleInput eller ReadFile .

Ansvarsfraskrivelse:Ovenstående er blevet testet på Windows 8 64bit, kompileret til 32 og 64 bit, Release- og Debug-konfigurationer.