0

I created an ConsoleEventHandler based on the following link described: https://www.meziantou.net/detecting-console-closing-in-dotnet.htm

It works perfectly for me. Currently I wish it can handle SIGTERM from both Windows and Linux. Does anybody has some clue about how to optimize it in C#? The following code needs to be optimized in two parts:

  1. can load Kernel32 in docker. Currently it fails in "System.DllNotFoundException: Unable to load shared library 'Kernel32' or one of its dependencies. "
  2. Support linux system;

The source code:

class Program
{
    // https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms686016.aspx
    [DllImport("Kernel32")]
    private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);

    // https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms683242.aspx
    private delegate bool SetConsoleCtrlEventHandler(CtrlType sig);

    private enum CtrlType
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT = 1,
        CTRL_CLOSE_EVENT = 2,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT = 6
    }

    static void Main(string[] args)
    {
        // Register the handler
        SetConsoleCtrlHandler(Handler, true);

        // Wait for the event
        while (true)
        {
            Thread.Sleep(50);
        }
    }

    private static bool Handler(CtrlType signal)
    {
        switch (signal)
        {
            case CtrlType.CTRL_BREAK_EVENT:
            case CtrlType.CTRL_C_EVENT:
            case CtrlType.CTRL_LOGOFF_EVENT:
            case CtrlType.CTRL_SHUTDOWN_EVENT:
            case CtrlType.CTRL_CLOSE_EVENT:
                Console.WriteLine("Closing");
                // TODO Cleanup resources
                Environment.Exit(0);
                return false;

            default:
                return false;
        }
    }
}
Deritha
  • 67
  • 2
  • 9
  • What exactly are you looking to "optimize"? – pinkfloydx33 Jun 18 '20 at 23:04
  • Add the source code I'm using. Do you have any suggestion about my 2 questions? Thanks – Deritha Jun 19 '20 at 21:23
  • A try/catch around the `SetConsoleCtrlHandler` will deal with the lack of `kernel32.dll` on linux. Then you need to add an equivalent that calls `signal()` to install a SIGTERM handler that should do pretty much the same thing. Note that it's standard practice for the signal handler (whether Win32 console control signal or POSIX SIGTERM) to set an event that triggers orderly shutdown of the main program, rather than just exiting instantly in the middle of ... well you don't know what the main thread is in the middle of! – Ben Voigt Aug 12 '21 at 16:02

1 Answers1

-1

Not sure if you still need an answer for it, but you could either go for any solution mentioned here: Detect when console application is closing/killed?

Or you could use the Console.CancelKeyPress and AppDomain.CurrentDomain.ProcessExit Events. Both are working on Linux. Cheers!

  • 1
    OP asks how to port his code to Linux. Your answer isn't related. – cassandrad Aug 12 '21 at 16:23
  • How is my answer not related? Since kernel32 is not working on Linux, there is only two possibilities (inC#) right now to catch these signals on Linux and these are Console.CancelKeyPress and AppDomain.CurrentDomain.ProcessExit. So instead of using kernel32.dll OP can register to these events and catch all Signals. – Johannes Aug 18 '21 at 11:51
  • That's just poorly copy pasted code without addressing OPs task as I see it. In that answer you provided I see two strange things: the first thing is why catch `SIGUSR1` and close the app on that signal? And the second thing is how Linux version handles logoff? Considering `ProcessExit` I'm no sure that it handles logoff too. – cassandrad Aug 18 '21 at 12:32