2

Powershell appears to have a buffer that stores unwanted input prior to a call to the ReadKey() method, and I need it to not do that. Is there a way to nullify the buffer or block input to it?

My script is supposed to take input at various points throughout execution. It does take input absolutely fine. The problem is when I'm between ReadKey() calls and some keys get accidentally pressed. Those keys get stored in some sort of invisible queue of pressed keys, then they all get fed to the next ReadKey() call automatically, which utterly defeats the purpose of prompting the user for intentional input, therefore defeating the script.

I've searched for an answer to this all over, but part of the problem is that this issue is so hard to describe in a short search term! I've tried using KeyAvailable() to prevent input from being recorded until the script is ready to prompt for it, but KeyAvailable() still concedes to the invisible buffer of keystrokes made during code execution. I've also tried clearing the variable that I store the keystroke in at the start of the loop, but the unintended keystrokes still get fed to the next ReadKey(). I've provided a mock version of the code as an example

$loop = $true

do {

     # Empties any previously stored value in $key.
     $key = $null

     write-host "Waiting 10 seconds to simulate script running"

     # This simulated area is where extra keyboard input is pressed unintentionally (or intentionally for demonstration purposes).
     Start-Sleep 10

     write-host "Ok, monkeys. Press any key to loop the simulation."

     # Wait for input from the user, record keystroke to $key.key.
     $key = [console]::ReadKey()

     # Report the status of $key.key
     write-host "`nKEY ="$key.key

     if ($key.key -eq "Enter") {

         $loop = $false

     }

} while ($loop -eq $true)

There are unfortunately no error messages, as I suspect that this is intended behavior by the Powershell devs (maybe not, idk). I expect to be able to run the script and not have ANY input recorded until the script is sitting on the ReadKey() call waiting for the keystroke. Instead, this example outputs the first keystroke made during script execution between ReadKey() calls, loops over, then outputs the second keystroke, and so on and so forth. When the keystrokes are exhausted, it will sit and wait for input like expected.

1 Answer 1

5

You should consider using the following instead of [console]::readkey()

$HOST.UI.RawUI.Flushinputbuffer()
write-host "Ok, monkeys. Press any key to loop the simulation."
$HOST.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”) | OUT-NULL
$HOST.UI.RawUI.Flushinputbuffer()

That will flush the buffer, then wait for a key press, and flush that key from the buffer after it is pressed. It doesn't work in the ISE, but if you're using the console it will work fine.

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

4 Comments

Perfect. Works better than ever. I should have known there were commands for an input buffer. Thanks for bringing that to my attention.
If you run a script with that code from Powershell ISE you'll get Exception calling "FlushInputBuffer" with "0" argument(s): "The method or operation is not implemented."
Right, I even said in my answer that it does not work in the ISE.
You can still use [Console]::ReadKey when using $Host.UI.RawUI.FlushInputBuffer()

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.