79 lines
No EOL
2.2 KiB
C#
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
|
|
}
|
|
} |