The simplest solution is to only react to keypresses that result in a printable character, and then evaluate which character was pressed via a switch
statement.
# Wait for a printable character to be pressed.
while (($char=($host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')).Character) -eq 0) {}
# Evaluate it.
switch -CaseSensitive ($char) {
'a' { 'You pressed a' }
'A' { 'You pressed A' }
default { 'You pressed neither a nor A' }
}
Note: While modifier keys Shift, Control, and Alt by themselves do not count as keypresses, combinations with a printable character do; therefore, for instance, Alt-a is treated the same as 'a'
, and Control-a as control character START OF HEADING, U+0001
.
If you want to avoid that, use the following variation instead:
# Wait for a printable character to be pressed, but only if not combined
# with Ctrl or Alt.
while (($key=$host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')).Character -eq 0 -or
$key.ControlKeyState -notin 0, 'ShiftPressed') {}
$char = $key.Character
Note: This works on Windows only - on Unix-like platforms, the .ControlKeyState
property is apparently always 0
.
However, if you use [Console]::ReadKey()
instead, you can make it work on Unix-like platforms too - which assumes that you're willing to assume that your script always runs in a console (terminal), and not other kinds of PowerShell hosts.
# Wait for a printable character to be pressed, but only if not combined
# with Ctrl or Alt.
while (($key = [Console]::ReadKey($true)).KeyChar -eq 0 -or
$key.Modifiers -notin 0, 'Shift') {}
$char = $key.KeyChar