第二次打开控制台后尝试调用Console.Clear()时出现异常

时间:2017-11-29 13:11:02

标签: c#

我正在尝试通过点击按钮从winform应用程序打开控制台。我通过以下代码执行此操作。

[DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool AllocConsole();

    [DllImport("kernel32.dll")]
    static extern Boolean FreeConsole();

private void button1_Click(object sender, EventArgs e)
    {
        int userInput = 0;
        AllocConsole();

        do
        {
            Console.Clear();
            Console.WriteLine("Hello World");
            Console.WriteLine("Select 1 or 2");
            int.TryParse(Console.ReadLine(), out userInput);
        } while (userInput != 1 && userInput != 2);

        FreeConsole();
    }

第一次打开控制台时,它运行正常。尝试再次打开控制台将正常工作,但一旦调用Console.Clear();,我得到:

  

mscorlib.dll中出现未处理的“System.IO.IOException”类型异常

     

其他信息:句柄无效。

Console.WriteLine();Console.ReadLine();会引发同样的异常。 我尝试过thisthisthis提出的解决方案,但我最终得到的结果是“句柄无效”。 Console.Clear();上的错误。

我尝试了一些其他代码:

    [DllImport("kernel32.dll",
        EntryPoint = "GetStdHandle",
        SetLastError = true,
        CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall)]
    private static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll",
        EntryPoint = "AllocConsole",
        SetLastError = true,
        CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall)]
    private static extern int AllocConsole();

    [DllImport("kernel32.dll")]
    static extern Boolean FreeConsole();


    private const int STD_OUTPUT_HANDLE = -11;
    private const int MY_CODE_PAGE = 437;

private void button1_Click(object sender, EventArgs e)
    {
        int userInput = 0;
        AllocConsole();

        IntPtr stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
        SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
        FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
        Encoding encoding = System.Text.Encoding.GetEncoding(MY_CODE_PAGE);
        StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
        standardOutput.AutoFlush = true;
        Console.SetOut(standardOutput);
        Stream streamIn = Console.OpenStandardInput();
        TextReader readerIn = new StreamReader(streamIn);
        Console.SetIn(readerIn);

        do
        {
            Console.Clear();
            Console.WriteLine("Hello World");
            Console.WriteLine("Select 1 or 2");
            int.TryParse(Console.ReadLine(), out userInput);
        } while (userInput != 1 && userInput != 2);

        FreeConsole();
    }

这似乎适用于Console.WriteLine();Console.ReadLine();,但我仍无法绕过Console.Clear();引发的异常。谁能告诉我,如果我错过了什么?

1 个答案:

答案 0 :(得分:2)

我怀疑可以多次连接/分离到控制台。据我所知the code of private static IntPtr ConsoleInputHandle(同样适用于ConsoleOutputHandle),句柄在首次使用时初始化一次,因此当您从控制台分离进程并再次重新附加时,句柄无效

因此,根据需要使用Console类是不可行的(我也不知道任何可用作控制台和Win32应用程序的实例示例 - 我见过的大多数应用程序都提供了两个版本of .exe)。

如果您确实需要Windows控制台,我猜您可以尝试在Windows API上方提供自己的控制台包装器。如果你只需要控制台的外观,你可以使用你自己的#34;类似控制台的"窗口。