1

OS: Windows 10 Enterprise 1703 64-bit

I cannot allocate and free a console more than once without loosing the Console.ReadKey() functionality in a windows form application. This question is similiar to Exception when using console window in a form application but the answer is missing out on the Console.ReadKey() function.

The following code works for the first execution only. One receives a new console window and the user has to press any key. On the second execution the text is displayed as well but Console.ReadKey() throws a System.InvalidOperationException.

System.InvalidOperationException: 'Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.'

Left out the DllImport declarations within the static Win32Wrapper class for brevity.

Win32Wrapper.AllocConsole();

// set standard out handle to console window
var ConOut = Win32Wrapper.CreateFile(
    "CONOUT$",
    GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
    ShareMode.FILE_SHARE_WRITE,
    IntPtr.Zero,
    CreationDisposition.OPEN_EXISTING,
    0,
    IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, ConOut);

// set stadard in handle to console window
var ConIn = Win32Wrapper.CreateFile(
    "CONIN$",
    GenericAccessRight.GENERIC_READ | GenericAccessRight.GENERIC_WRITE,
    ShareMode.FILE_SHARE_READ,
    IntPtr.Zero,
    CreationDisposition.OPEN_EXISTING,
    0,
    IntPtr.Zero
);
Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, ConIn);

Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true });
Console.SetIn(new StreamReader(Console.OpenStandardInput()));

Console.WriteLine("Hello World!"); // works every time
Console.Read();                    // works every time
Console.ReadKey(true);             // second call: InvalidOperationException

Win32Wrapper.CloseHandle(ConIn)
Win32Wrapper.CloseHandle(ConOut)

return Win32Wrapper.FreeConsole();
3
  • 1
    This isn't going to work out. Convert your program to be a console app. Commented Oct 18, 2019 at 13:08
  • Not possible because its a GUI application. Commented Oct 18, 2019 at 13:41
  • So you'll likely need two distinct executables and some IPC. Commented Oct 18, 2019 at 13:50

1 Answer 1

1

I found a way to simulate the above behaviour by not destroying the console I created before but instead simply hiding and displaying it again.

if (FirstTime)
{
  FirstTime = false;
  Win32Wrapper.SetStdHandle(Win32Wrapper.STD_OUTPUT_HANDLE, HWND.Zero);
  Win32Wrapper.SetStdHandle(Win32Wrapper.STD_INPUT_HANDLE, HWND.Zero);
  Win32Wrapper.AllocConsole(); // show implicitly
}
else
{
  Console.Clear(); // clear => simulate new console
  Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 5); // show (again)
}

Console.WriteLine("Hello World!");
Console.Read();
Console.ReadKey(true);

Win32Wrapper.ShowWindow(Win32Wrapper.GetConsoleWindow(), 0); // hide

Only the first function call allocates a new console further calls only show the already existing console again. All I need is a static variable to take track of it.

Sign up to request clarification or add additional context in comments.

1 Comment

You can mark yourself to help others with the same problems

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.