using System.Runtime.InteropServices; namespace SinMaiLauncher.Interops; internal static class ConsoleInterops { private static class NativeConsole { [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AllocConsole(); [DllImport("kernel32.dll")] public static extern nint GetStdHandle(int nStdHandle); [DllImport("kernel32.dll")] public static extern bool SetConsoleMode(nint hConsoleHandle, int dwMode); [DllImport("kernel32.dll", SetLastError = true)] public static extern nint GetConsoleWindow(); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool AttachConsole(uint dwProcessId); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] public static extern bool FreeConsole(); [DllImport("kernel32.dll")] public static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate? HandlerRoutine, bool Add); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool GenerateConsoleCtrlEvent(ConsoleCtrlEvent ctrlEvent, uint processGroupId); public delegate bool ConsoleCtrlDelegate(uint ctrlType); // 控制台控制事件类型 public enum ConsoleCtrlEvent { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT = 1 } public const int STD_INPUT_HANDLE = -10; public const int ENABLE_QUICK_EDIT_MODE = 0x0040; public const int ENABLE_EXTENDED_FLAGS = 0x0080; } public static class ExternalProcess { public static IntPtr? GetConsoleWindow(uint pid) { if (NativeConsole.AttachConsole(pid) == false) return null; var handle = NativeConsole.GetConsoleWindow(); return handle; } public static bool DisableQuickEdit(uint pid) { if (NativeConsole.AttachConsole(pid) == false) return false; nint handle = NativeConsole.GetStdHandle(NativeConsole.STD_INPUT_HANDLE); // 禁用快速编辑模式 int mode = NativeConsole.ENABLE_EXTENDED_FLAGS; return NativeConsole.SetConsoleMode(handle, mode); } public enum ResultOfSendCtrlC { Success = 0, AttachConsoleFailed = 1, GenerateCtrlEventFailed = 2 } public static ResultOfSendCtrlC SendCtrlC(uint processId) { // 尝试附加到指定进程的控制台 if (!NativeConsole.AttachConsole(processId)) return ResultOfSendCtrlC.AttachConsoleFailed; // 设置控制处理程序以避免自己进程接收到信号 NativeConsole.SetConsoleCtrlHandler(null, true); // 发送CTRL_C_EVENT if (!NativeConsole.GenerateConsoleCtrlEvent(NativeConsole.ConsoleCtrlEvent.CTRL_C_EVENT, 0)) { return ResultOfSendCtrlC.GenerateCtrlEventFailed; } // 释放控制台 NativeConsole.FreeConsole(); // 如果没有异常发生,退出代码为Success return ResultOfSendCtrlC.Success; } } public static class CurrentProcess { public static void ConsoleAllocate() => NativeConsole.AllocConsole(); public static void ConsoleDisableQuickEdit() { nint handle = NativeConsole.GetStdHandle(NativeConsole.STD_INPUT_HANDLE); // 禁用快速编辑模式 int mode = NativeConsole.ENABLE_EXTENDED_FLAGS; NativeConsole.SetConsoleMode(handle, mode); } public static void ConsoleWindowSetParent(Control container) { var consoleHandle = NativeConsole.GetConsoleWindow(); // 将控制台窗口设置为 Panel 的子窗口 WindowInterops.SetParent(consoleHandle, container.Handle); // 修改控制台窗口样式,去掉边框 WindowInterops.RemoveBorderVisible(consoleHandle); } public static void ConsoleWindowFill(Control container) { WindowInterops.FillWindow(NativeConsole.GetConsoleWindow(), container); } } }