chore: rework windows signal notify

This commit is contained in:
Louis Seubert 2024-05-10 21:40:41 +02:00
parent b54acec2f2
commit b7517a7fee
Signed by: louis9902
GPG key ID: 4B9DB28F826553BD
3 changed files with 50 additions and 30 deletions

View file

@ -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);
}
}

View file

@ -1,8 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -1,43 +1,26 @@
using System.Globalization; namespace Geekeey.Extensions.Process.Win.Notify;
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);
}
internal static class Program internal static class Program
{ {
public static int Main(string[] args) public static int Main(string[] args)
{ {
var processId = uint.Parse(args[0], CultureInfo.InvariantCulture); var processId = uint.Parse(args[0]);
var signal = uint.Parse(args[1], CultureInfo.InvariantCulture); var signal = uint.Parse(args[1]);
// detach from the current console, if one is attached to the process. // detach from the current console, if one is attached to the process.
Interop.FreeConsole(); Interop.Kernel32.FreeConsole();
var success = var success =
// attach to the target process group // 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 // 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 // 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();
} }
} }