I'm writing a console application using Net6. It runs on Raspberry, Ubuntu and Windows.
The user can quit the application by pressing Q, Ctrl-C or close the window.
I'm detecting the Q press in my static void Main method
bool requestShutdown = false;
bool close = false;
while (!close && !requestShutdown)
{
if (Console.KeyAvailable)
{
var keyPressed = Console.ReadKey(true);
close = (keyPressed.Key == ConsoleKey.Q);
if (close) DoLogging("Requesting shutdown (Q)");
}
Thread.Sleep(0);
Thread.Sleep(250);
}
ShutDown();
where I'm also detecting the Ctrl-C using
Console.CancelKeyPress += Console_CancelKeyPress;
...
private static void Console_CancelKeyPress(object? sender, ConsoleCancelEventArgs e)
{
DoLogging("Requesting shutdown (Ctrl-C)");
requestShutdown = true;
}
This all works nice in Windows and Raspberry (running through Putty). The
ShutDown();
block is called when either Q or Ctrl-C is pressed. So far so good !
However in Windows, it is possible for the user to just close the window by pressing the close button or use Alt-F4.
I know that I can capture this using the code
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(ConsoleCloseCtrlType signal);
private static EventHandler handler;
...
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
handler += new EventHandler(Handler);
SetConsoleCtrlHandler(handler, true);
}
...
private static bool Handler(ConsoleCloseCtrlType signal)
{
DoLogging($"Requesting shutdown ({signal})");
ShutDown();
return true;
}
but, this obviously will not work in Linux OS:es, since the Kernel32 import throws an exception on a Raspberry.
What I have tried:
I thought that it would be easy to use some kind of compiler directive to prevent the Kernel32 code to be included, but my Google Fu skills does not seem to be good enough to find a solution and trust me, I spent a number of hours trying to find it.
I use
dotnet publish
to build the code for the three targets (Windows, Linux-x64 and Linux-arm) but I can't seem to find any way to just include the Kernel32 for the Windows build.
I've looked at ideas such as
this but since I build for all three platforms on my Windows machine that suggestion does not work.
Also, since it is the Kernel32 dll I can't really see how I can load it dynamically at runtime.
I'm most likely missing something very obvious so if someone could enlighten me or give me a push in the right direction it would be most appreciated.
Thanks in advance,
King regards
Magnus