Why ReadKey throws exception while running a .net-core console app from Git Bash?

Viewed 923

This is the code:

ConsoleKeyInfo cki;

while((cki = Console.ReadKey(true)).Key != ConsoleKey.Escape)
{
    Console.WriteLine(cki.Key);
}

When i run it from cmd or powershell with dotnet run everything works fine. However when i run it from Git Bash it throws the following exception:

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

3 Answers

Presumably, then, Git Bash is using IO redirection - which it is allowed to do - and the others ... aren't. The solution, then, is to use Read rather than ReadKey - at least if redirection is in play. You can probably detect this via Console.IsInputRedirected - and choose the most useful strategy for what is possible, but: you won't be able to detect keys in the same way, so you may need to have a slightly different user-experience in this scenario.

Basically, 100% of what Marc said in his answer.

Side note to that: under linux-like terminals (and git-bash is one of them) the typical (or even standard) way of aborting an interactive application/script that currently blocks/holds the console is pressing Control+C. net-core console applications support that. It's much easier to make it quite via control+c than to try to peek what keys are being pressed.

IIRC, net-core applications automatically detect pressing control+C and by default they just quit, and that makes the console usable by the user again. This means that no extra code needs to be written and even while(true) loops could be halted with this (the event-handler that handles control+c is ran on the thread pool, regardless of the main thread being busy).

https://docs.microsoft.com/en-us/dotnet/api/system.console.cancelkeypress?view=netcore-3.1

By default, the Cancel property is false, which causes program execution to terminate when the event handler exits. Changing its property to true specifies that the application should continue to execute.

This still happens on both OS, Windows and Linux, if we are dealing with unicode that have a rune width greater than 1 on a window resizing with Net5.0.

Related