WinForm调用AllocConsole开控制台后Console.ReadKey抛异常怎么解决?
问题产生原因
- Windows Forms 项目默认的输出类型为「Windows 应用程序」,这类程序启动时.NET运行时会直接解绑标准输入、输出、错误流和控制台的关联。即便后续通过
AllocConsole()Win32 API分配了新的控制台,.NET内置的Console类也不会自动绑定到新控制台的流,因此会检测不到有效控制台,引发InvalidOperationException异常。 - 手动分配的控制台输入缓冲区默认没有和
Console类的输入流绑定,直接调用Console.Read()也会因为读取不到有效流内容,无法识别按键输入。
解决方法
提供两种可选方案,按需选择即可:
方案1:修改项目输出类型(最稳定,推荐)
- 右键你的WinForms项目,选择「属性」-「应用」选项卡,把「输出类型」从「Windows 应用程序」修改为「控制台应用程序」,删除原有
AllocConsole()相关代码即可。 - 该方案下程序启动时会自动完成控制台流的绑定,窗体也可以正常加载运行,若不需要默认显示控制台,可在程序启动时调用
FreeConsole()Win32 API隐藏控制台,需要显示时再调用API显示即可。
方案2:手动绑定控制台流(不修改项目输出类型)
如果需要保留原有项目配置,仅在特定场景动态分配控制台,可在调用AllocConsole()后手动关联控制台的输入输出流,完整代码如下:
using System.IO; using System.Runtime.InteropServices; public static class ConsoleHelper { [DllImport("kernel32")] private static extern bool AllocConsole(); [DllImport("kernel32", SetLastError = true)] private static extern IntPtr GetStdHandle(int nStdHandle); private const int STD_INPUT_HANDLE = -10; private const int STD_OUTPUT_HANDLE = -11; private const int STD_ERROR_HANDLE = -12; public static void CreateConsole() { AllocConsole(); // 关联标准输出流 IntPtr outHandle = GetStdHandle(STD_OUTPUT_HANDLE); FileStream outStream = new FileStream(outHandle, FileAccess.Write); StreamWriter outWriter = new StreamWriter(outStream) { AutoFlush = true }; Console.SetOut(outWriter); // 关联标准错误流 IntPtr errHandle = GetStdHandle(STD_ERROR_HANDLE); FileStream errStream = new FileStream(errHandle, FileAccess.Write); StreamWriter errWriter = new StreamWriter(errStream) { AutoFlush = true }; Console.SetError(errWriter); // 关联标准输入流 IntPtr inHandle = GetStdHandle(STD_INPUT_HANDLE); FileStream inStream = new FileStream(inHandle, FileAccess.Read); StreamReader inReader = new StreamReader(inStream); Console.SetIn(inReader); } }
调用上述ConsoleHelper.CreateConsole()方法完成控制台初始化后,再调用Console.ReadKey()、Console.Read()即可正常读取按键输入。
内容的提问来源于stack exchange,提问作者BennoDual
相关产品推荐
相关产品推荐

