0

I have created a Windows Forms Application. In special situations, I open a Console-Window with

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


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

When I after call Console.ReadKey() i get an 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.

When I use Console.Read() it will not work. No keystroke is recognized.

Can someone help me, whats the problem here? Thank you.

BennoDual
  • 5,865
  • 15
  • 67
  • 153
  • 1
    Please edit to place the full code example IN your question of what you have tried so we may best assist you. https://learn.microsoft.com/en-us/dotnet/api/system.console.readkey?view=net-5.0 and https://learn.microsoft.com/en-us/dotnet/api/system.console.read?view=net-5.0 for example of use – Mark Schultheiss May 21 '21 at 16:41
  • 1
    Instead of doing the dllImport stuff try going into the project properties and under application change the output type to console application. That seems to work for me. – cc959 May 21 '21 at 16:42
  • @CatCraft959 That allows you to optionally show the console window? – ProgrammingLlama May 21 '21 at 16:43
  • I have added the full Code. – BennoDual May 21 '21 at 16:45
  • @Llama No it just shows it all the time but is is relatively easy to hide then: https://stackoverflow.com/questions/3571627/show-hide-the-console-window-of-a-c-sharp-console-application – cc959 May 21 '21 at 16:45

1 Answers1

0

As you might see, your output goes to Visual Studio console, not opened one. To fix that issue you need to reopen console output stream:

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

Note, that new FileStream("CONOUT$", ...) and Console.OpenStandardInput() won't work. I've just tested it with Windows.Forms application. Console.ReadKey works correctly for me. Create file and constants is from kernel32.dll

Alex
  • 526
  • 2
  • 8