using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace Conjure.Arcade.Overlay { public static class WindowUtils { [DllImport("kernel32.dll")] private static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); [DllImport("kernel32.dll")] private static extern uint SuspendThread(IntPtr hThread); [DllImport("kernel32.dll")] private static extern uint ResumeThread(IntPtr hThread); [DllImport("kernel32.dll")] private static extern bool CloseHandle(IntPtr hObject); [Flags] private enum ThreadAccess : int { SUSPEND_RESUME = 0x0002 } [DllImport("user32.dll")] private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect); [StructLayout(LayoutKind.Sequential)] public struct Rect { public int Left; public int Top; public int Right; public int Bottom; } public static bool GetWindowBounds(IntPtr handle, out Rect rect) { rect = new Rect(); return GetWindowRect(handle, ref rect) != IntPtr.Zero; } public static Process? FindProcess(string processName) { var processes = Process.GetProcessesByName(processName); return processes.Length > 0 ? processes[0] : null; } public static void SuspendProcess(Process process) { foreach (ProcessThread thread in process.Threads) { var threadHandle = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); if (threadHandle != IntPtr.Zero) { try { SuspendThread(threadHandle); } finally { CloseHandle(threadHandle); } } } } public static void ResumeProcess(Process process) { foreach (ProcessThread thread in process.Threads) { var threadHandle = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); if (threadHandle != IntPtr.Zero) { try { ResumeThread(threadHandle); } finally { CloseHandle(threadHandle); } } } } } }