How disable Control-C in a console program.

By | December 10, 2021

Control-C (CTRL+C) key combinations sends special signal to console processes, when a console window has the keyboard focus. By default Control-C (also Control-Break) signal is treated not as keyboard input but aborts all console processes attached to this console. In GUI applications Control-C is treated differently and usually is used to copy highlighted text or image to clipboard.
However console application may intercepts Control-C signal to process it differently than process interruption.
The first example shows how to capture Control-C signal in C++ Linux code. When application is started without argument the special Control-C processing is off. It application has at least on argument Control-C signal is captured and processed by CustomCtrlC function. The source code:

#include <stdio.h>
#include <signal.h>
void CustomCtrlC(int nSignal);
int main(int n, char ** s)
{
        if(n>1)
        {
                // Custom ctrl-c processing
                printf("Custom Ctrl-C processing\n");
                signal(SIGINT, &CustomCtrlC);
        }
        printf("Press ENTER key to exit\n");
        char chr = getchar();
        printf("ENTER key was pressed\n");
        return 0;
}
void CustomCtrlC(int nSignal)
{
        printf("Signal with code %d received\n", nSignal);
}

Results:


# ./signal
Press ENTER key to exit
^C
# ./signal argument
Custom Ctrl-C processing
Press ENTER key to exit
^CSignal with code 2 received
^CSignal with code 2 received
^CSignal with code 2 received

ENTER key was pressed
#

C# example:

using System;
using System.Runtime.InteropServices;
namespace signal
{
    class Program
    {
        public delegate bool HandlerRoutine(CtrlTypes CtrlType);
        static HandlerRoutine handler;
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int GetLastError();
 
        public enum CtrlTypes
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT,
            CTRL_CLOSE_EVENT,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT
        }
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                Console.WriteLine("Custom Ctrl-C processing");

                handler = new HandlerRoutine(ConsoleCtrlC);
                if (!SetConsoleCtrlHandler(handler, true))
                {
                    Console.WriteLine("SetConsoleCtrlHandle ret value: " + GetLastError().ToString(), "");
                }
            }
            Console.WriteLine("Press ENTER to exit");
            ConsoleKeyInfo keyInfo = new ConsoleKeyInfo('A', ConsoleKey.A, false, false, false);
            while (ConsoleKey.Enter != keyInfo.Key)
            {
                keyInfo = Console.ReadKey();
            }
            Console.WriteLine("Exited");
        }
        private static bool ConsoleCtrlC(CtrlTypes ctrlType)
        {
            Console.WriteLine("ConsoleCtrlC ctrType: {0}", ctrlType);
            switch (ctrlType)
            {
                case CtrlTypes.CTRL_C_EVENT:
                case CtrlTypes.CTRL_BREAK_EVENT:
                    // disable ctrl/c and ctrl/break
                    break;
            }
            return true;
        }

    }
}

Result (Start with argument to turn on custom Control-C processing):


D:\Projects\signal\signal\bin\Debug\net5.0>signal.exe
Press ENTER to exit
^C
D:\Projects\signal\signal\bin\Debug\net5.0>signal.exe
Press ENTER to exit
qwerty^C
D:\Projects\signal\signal\bin\Debug\net5.0>signal.exe 1
Custom Ctrl-C processing
Press ENTER to exit
ConsoleCtrlC ctrType: CTRL_C_EVENT
ConsoleCtrlC ctrType: CTRL_C_EVENT
ConsoleCtrlC ctrType: CTRL_C_EVENT
ConsoleCtrlC ctrType: CTRL_C_EVENT
ConsoleCtrlC ctrType: CTRL_C_EVENT
Exited

Leave a Reply

Your email address will not be published. Required fields are marked *