process/src/Process/Execution/ProcessHandle.Windows.cs
Louis Seubert b54acec2f2
Some checks failed
default / default (8.0) (push) Failing after 26s
feat: initial project commit
2024-05-08 22:13:03 +02:00

79 lines
No EOL
2.2 KiB
C#

using System.Diagnostics;
using System.Runtime.Versioning;
using System.Text;
namespace Geekeey.Extensions.Process;
internal partial class ProcessHandle
{
private const string CSharpSourceText =
"""
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool AttachConsole(uint p);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleCtrlHandler(uint p, bool a);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GenerateConsoleCtrlEvent(uint e, uint p);
public static int NotifyCtrlEvent(uint pid, uint sig)
{
// detach from the current console, if one is attached to the process.
FreeConsole();
var success =
// attach to the target process group
AttachConsole(pid) &&
// set to ignore signals on self, so the proper exit code can be return
SetConsoleCtrlHandler(0, true) &&
// send the signal to the process group
GenerateConsoleCtrlEvent(sig, 0);
return success ? 0 : Marshal.GetLastWin32Error();
}
""";
private const string PowerShellSourceText =
"""
Add-Type -Namespace 'Win32' -Name 'Notify' -Language CSharp -MemberDefinition '{0}';
exit [Win32.Notify]::NotifyCtrlEvent({1}, {2})
""";
[SupportedOSPlatform("windows")]
private static bool SendCtrlSignal(int processId, ConsoleCtrlEvent ctrl)
{
using var process = new System.Diagnostics.Process();
var text = string.Format(PowerShellSourceText, CSharpSourceText, processId, (uint)ctrl);
text = Convert.ToBase64String(Encoding.Unicode.GetBytes(text));
process.StartInfo = new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = $"-NoLogo -NoProfile -ExecutionPolicy Bypass -EncodedCommand {text}",
CreateNoWindow = true,
UseShellExecute = false
};
if (!process.Start())
return false;
if (!process.WaitForExit(30_000))
return false;
return process.ExitCode == 0;
}
internal enum ConsoleCtrlEvent
{
CTRL_C_EVENT = 0, // SIGINT
CTRL_BREAK_EVENT = 1, // SIGQUIT
CTRL_CLOSE_EVENT = 2, // SIGHUP
CTRL_LOGOFF_EVENT = 5, // SIGHUP
CTRL_SHUTDOWN_EVENT = 6, // SIGTERM
}
}