Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception when trying to call Console.Clear() after opening a console a second time

Tags:

c#

I'm trying to open a console from a winform application from a button click. I'm doing this via the code below.

[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();
    }

The first time the console is opened, it works fine. Attempting to open the console a second time will work fine, but once Console.Clear(); is called, I get:

An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll

Additional information: The handle is invalid.

The same exception will be thrown on Console.WriteLine(); and Console.ReadLine();. I've tried the proposed solutions from this, this, and this, but I end up with the same "handle is invalid." error on Console.Clear();.

Some additional code I've tried:

    [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();
    }

This seems to be ok for Console.WriteLine(); and Console.ReadLine(); but I still can't get around the exception being thrown by Console.Clear();. Can anyone tell me if I'm missing something?

like image 578
Sudsy1002 Avatar asked Sep 17 '25 04:09

Sudsy1002


1 Answers

I doubt it is possible to attach/detach to console multiple times. As far as I understand the code of private static IntPtr ConsoleInputHandle (the same goes for ConsoleOutputHandle), the handle is initialized once on first usage, so when you detach the process from console and re-attach it once again the handle is invalid.

So imho it is not feasible to use Console class as you want (nor do I know any live examples of programs working both as console and Win32 app - the most applications I've seen provide two versions of .exe).

If you really need Windows console I guess you can try to provide your own console wrapper above Windows API. If you need only the looks of console you can go with rendering of your own "console-like" window.

like image 116
Sergey.quixoticaxis.Ivanov Avatar answered Sep 19 '25 11:09

Sergey.quixoticaxis.Ivanov