首页 > 解决方案 > Console.ReadKey() 产生异常

问题描述

我创建了一个 Windows 窗体应用程序。在特殊情况下,我打开一个控制台窗口

    public static void CreateConsole() {
        AllocConsole();
    }


    [DllImport("kernel32")]
    private static extern bool AllocConsole();

当我打电话后Console.ReadKey()我得到一个InvalidOperationException

当任一应用程序没有控制台或控制台输入已从文件重定向时,无法读取密钥。试试 Console.Read。

当我使用Console.Read()它时,它不起作用。没有识别出击键。

有人可以帮助我,这里有什么问题?谢谢你。

标签: c#

解决方案


如您所见,您的输出进入 Visual Studio 控制台,而不是打开的控制台。要解决该问题,您需要重新打开控制台输出流:

if (AllocConsole())
{
    var outHandle = CreateFile("CONOUT$", 
        (uint)(FileConsts.FILE_GENERIC_WRITE | FileConsts.FILE_GENERIC_READ), 
        (uint)(FileConsts.FILE_SHARE_WRITE | FileConsts.FILE_SHARE_READ), 
        0,
        FileConsts.OPEN_EXISTING,
        FileConsts.FILE_ATTRIBUTE_NORMAL, 0);
   
    var inHandle = CreateFile("CONIN$",
        (uint)(FileConsts.FILE_GENERIC_WRITE | FileConsts.FILE_GENERIC_READ),
        (uint)(FileConsts.FILE_SHARE_WRITE | FileConsts.FILE_SHARE_READ),
        0,
        FileConsts.OPEN_EXISTING,
        FileConsts.FILE_ATTRIBUTE_NORMAL, 0);

    if (!SetStdHandle(STD_OUTPUT_HANDLE, outHandle))
        throw new Exception("Can't set std handle");

    if (!SetStdHandle(STD_INPUT_HANDLE, inHandle))
        throw new Exception("Can't set std handle");

    //Just for handle .Dispose();
    var fileStream = new FileStream(new SafeFileHandle(outHandle, true), FileAccess.Write);
    var fileStreamRead = new FileStream(new SafeFileHandle(inHandle, true), FileAccess.Read);

    ConsoleKey read;
    while ((read = Console.ReadKey().Key) != ConsoleKey.Escape)
    {
        Console.WriteLine($"Printed {read}");
    }

    Console.WriteLine("Escape Pressed, exiting");

    SetStdHandle(STD_INPUT_HANDLE, IntPtr.Zero);
    SetStdHandle(STD_OUTPUT_HANDLE, IntPtr.Zero);
    fileStream.Dispose();
    fileStreamRead.Dispose();
    FreeConsole();
}

请注意,这new FileStream("CONOUT$", ...)Console.OpenStandardInput()不起作用。我刚刚使用 Windows.Forms 应用程序对其进行了测试。Console.ReadKey 对我来说可以正常工作。创建文件和常量来自 kernel32.dll


推荐阅读