Tag Archives: ReadKey

QuickTip: Read single key press using [System.Console] class

When building an interactive script capturing a single key press might be necessary. In the previous article, QuickTip: Read single key press from PowerShell console, I showed how this is possible using the $host variable. In this article I will show how to read a key press using the [System.Console] class and in particular the ReadKey method.

The following example uses ReadKey with a single argument, $true, to ensure that the result of the function is not output to the console. Omitting $true or passing on $false as an argument will result in the output being displayed in the console as well as stored in the variable. Have a look at the example here:

$KeyPress = [System.Console]::ReadKey($true)

Similarly to the $host object ReadKey method not only the key itself but also the modifiers are passed on to the console. Here is the result of this method:

PS> $KeyPress
KeyChar      Key      Modifiers
-------      ---      ---------
      J        J          Shift

The modifiers are slightly different from what the $host object output. To have a look at the possible values we dig a bit further into the object stored in $KeyPress:

PS> $KeyPress.Modifiers.GetType()
IsPublic      IsSerial                Name           BaseType
--------      --------                ----           --------
True              True    ConsoleModifiers        System.Enum
PS> [Enum]::GetNames([System.ConsoleModifiers])

For more information about the System.Console class have a look at its MSDN entry: Console Class


QuickTip: Read single key press from PowerShell console

When building an interactive script capturing a single key press might be necessary. This can be done by using the $host variable, specifically the ReadKey method. It is important to note that this method is only available in the PowerShell console this does not work in the PowerShell Integrated Scripting Environment (ISE).

A simple example: You might require your script to ask for Yes / No, using the Read-Host would allow the user to type in more than one character and the enter key would have to be pressed. In this scenario the ReadKey method is can be preferably, because it registers a single key press:

$KeyPress = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Now if we were to display the contents of the $KeyPress variable, we can see the following information:

PS> $KeyPress
VirtualKeyCode      Character      ControlKeyState      KeyDown
--------------      ---------      ---------------      -------
            89              y            NumLockOn         True

So the information contained that is captured by  this method not only contains the character, but also the type of key press as well as which additional ‘Control Keys’ were pressed. Control keys for example are the Numlock and Capslock status on your keyboard as well as Alt, Win and Ctrl keys. The control keys are part of the ControlKeyStates enumeration which can be enumerated using the [Enum] Class as shown in the following example:

PS> [Enum]::GetNames([System.Management.Automation.Host.ControlKeyStates])

For more information about using the GetNames method of the [System.Enum] class, please refer to my previous article: QuickTip: Enumerate objects with [System.Enum] class.

For example, if the goal is to construct a simple Y/N question using what we’ve learned so far can be placed in a while-loop:

$KeyOption = 'Y','N'
while ($KeyOption -notcontains $KeyPress.Character) {
 $KeyPress = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

And that how a single key press can be caught in a variable, adding in a switch or if-elseif-else statement will allow for action based on the key that has been pressed. Next week I will discuss an alternative to using the $host object for this purpose, stay tuned!