// Copyright 2026 sjackson0109 — Apache License 2.0
using System.Runtime.InteropServices;
namespace RDPWrap.Common;
///
/// Process creation and termination helpers. Mirrors ExecWait and KillProcess
/// from RDPWInst.dpr (console variant) and RDPConf MainUnit.pas (GUI variant).
///
public static class ProcessHelper
{
///
/// Creates a process from , waits for it to
/// exit, then returns true. The process window is hidden.
/// Mirrors the Delphi ExecWait procedure.
///
public static bool ExecWait(string commandLine, bool hideWindow = true)
{
var si = new NativeMethods.STARTUPINFO
{
cb = (uint)Marshal.SizeOf(),
dwFlags = hideWindow ? NativeMethods.STARTF_USESHOWWINDOW : 0u,
wShowWindow = hideWindow ? NativeMethods.SW_HIDE : (ushort)1
};
// CommandLine must be mutable — pass a copy
string cmdCopy = new(commandLine);
if (!NativeMethods.CreateProcess(null, cmdCopy, IntPtr.Zero, IntPtr.Zero,
true, 0, IntPtr.Zero, null, ref si, out var pi))
{
Console.Error.WriteLine(
$"[-] CreateProcess error (code {Marshal.GetLastWin32Error()}).");
return false;
}
NativeMethods.WaitForSingleObject(pi.hProcess, 0xFFFFFFFF);
NativeMethods.CloseHandle(pi.hThread);
NativeMethods.CloseHandle(pi.hProcess);
return true;
}
///
/// Terminates the process with . Mirrors the Delphi
/// KillProcess procedure.
///
public static void KillProcess(uint pid)
{
var hProc = NativeMethods.OpenProcess(NativeMethods.PROCESS_TERMINATE, false, pid);
if (hProc == IntPtr.Zero)
{
Console.Error.WriteLine(
$"[-] OpenProcess error (code {Marshal.GetLastWin32Error()}).");
return;
}
if (!NativeMethods.TerminateProcess(hProc, 0))
Console.Error.WriteLine(
$"[-] TerminateProcess error (code {Marshal.GetLastWin32Error()}).");
NativeMethods.CloseHandle(hProc);
}
}