From b7517a7feefb1c0ff6ea999800e7a336cbb80783 Mon Sep 17 00:00:00 2001 From: Louis Seubert Date: Fri, 10 May 2024 21:40:41 +0200 Subject: [PATCH] chore: rework windows signal notify --- src/Process.Win.Notify/Interop.cs | 38 ++++++++++++++++++ .../Process.Win.Notify.csproj | 3 +- src/Process.Win.Notify/Program.cs | 39 ++++++------------- 3 files changed, 50 insertions(+), 30 deletions(-) create mode 100644 src/Process.Win.Notify/Interop.cs diff --git a/src/Process.Win.Notify/Interop.cs b/src/Process.Win.Notify/Interop.cs new file mode 100644 index 0000000..bba2a2a --- /dev/null +++ b/src/Process.Win.Notify/Interop.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; + +namespace Geekeey.Extensions.Process.Win.Notify; + +internal static class Interop +{ + // ReSharper disable MemberHidesStaticFromOuterClass + + internal static class Libraries + { + internal const string Kernel32 = "kernel32.dll"; + } + + internal static class Kernel32 + { + public delegate bool ConsoleCtrlDelegate(uint dwCtrlEvent); + + [DllImport(Libraries.Kernel32)] + [SuppressGCTransition] + internal static extern int GetLastError(); + + [DllImport(Libraries.Kernel32)] + [SuppressGCTransition] + public static extern bool FreeConsole(); + + [DllImport(Libraries.Kernel32)] + [SuppressGCTransition] + public static extern bool AttachConsole(uint dwProcessId); + + [DllImport(Libraries.Kernel32)] + [SuppressGCTransition] + public static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? handlerRoutine, bool add); + + [DllImport(Libraries.Kernel32)] + [SuppressGCTransition] + public static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId); + } +} \ No newline at end of file diff --git a/src/Process.Win.Notify/Process.Win.Notify.csproj b/src/Process.Win.Notify/Process.Win.Notify.csproj index ccd7007..68a45ff 100644 --- a/src/Process.Win.Notify/Process.Win.Notify.csproj +++ b/src/Process.Win.Notify/Process.Win.Notify.csproj @@ -1,8 +1,7 @@  - + false Exe true - \ No newline at end of file diff --git a/src/Process.Win.Notify/Program.cs b/src/Process.Win.Notify/Program.cs index 6e736c2..799d327 100644 --- a/src/Process.Win.Notify/Program.cs +++ b/src/Process.Win.Notify/Program.cs @@ -1,43 +1,26 @@ -using System.Globalization; -using System.Runtime.InteropServices; - -namespace Geekeey.Extensions.Process.Win.Notify; - -internal static class Interop -{ - public delegate bool ConsoleCtrlDelegate(uint dwCtrlEvent); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool FreeConsole(); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool AttachConsole(uint dwProcessId); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? handlerRoutine, bool add); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent, uint dwProcessGroupId); -} +namespace Geekeey.Extensions.Process.Win.Notify; internal static class Program { public static int Main(string[] args) { - var processId = uint.Parse(args[0], CultureInfo.InvariantCulture); - var signal = uint.Parse(args[1], CultureInfo.InvariantCulture); + var processId = uint.Parse(args[0]); + var signal = uint.Parse(args[1]); // detach from the current console, if one is attached to the process. - Interop.FreeConsole(); + Interop.Kernel32.FreeConsole(); var success = // attach to the target process group - Interop.AttachConsole(processId) && + Interop.Kernel32.AttachConsole(processId) && // set to ignore signals on self, so the proper exit code can be return - Interop.SetConsoleCtrlHandler(null, true) && + Interop.Kernel32.SetConsoleCtrlHandler(null, true) && // send the signal to the process group - Interop.GenerateConsoleCtrlEvent(signal, 0); + Interop.Kernel32.GenerateConsoleCtrlEvent(signal, 0); - return success ? 0 : Marshal.GetLastPInvokeError(); + // we can use the kernel32 GetLastError here, instead of relaying on `Marshal.GetLastWin32Error`, because we + // are compiling this with a compiler which does not include gc. This can not cause gc pause which tampers with + // the last error code. + return success ? 0 : Interop.Kernel32.GetLastError(); } } \ No newline at end of file