Windows PowerShell Tip of the Week

Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us know.

Find more tips in the Windows PowerShell Tip of the Week archive.

Pausing a Script Until the User Presses a Key

One advantage to more graphical-oriented scripting languages is the fact that it’s easy to pause a script until the user is ready to continue. For example, suppose you have a VBScript script that needs to wait for the user to do something (like, say, put special paper in the printer) before it can continue. How can you pause the script until the user is ready to proceed? Well, one very easy way is simply to display a message box:

Once you do that the script will enter a state of suspended animation, and won’t continue until the user clicks OK. If the user never clicks OK, well, then the script will never continue. But that’s all right; after all, the whole idea is to not do anything until the user says it’s OK to do it.

With command-line oriented languages this becomes more of a problem. Granted, there are ways to display a message box using Windows PowerShell; however, doing so detracts a little from the command-line experience users expect from PowerShell. A much better, and more natural, approach would be to display the ubiquitous message long used by command-line executables:

Press any key to continue ...

At that point your script would pause until the user presses any key on the keyboard. If the user never presses a key on the keyboard, well, then the script will never continue. Which is exactly what we want it to do.

Or what we want it not to do, as the case may be.

Wishful thinking? Maybe. On the other hand, what’s really nice about Windows PowerShell is this: if there’s something you want to do then there’s a very good chance that PowerShell provides a way to do it. You want to pause a script until the user presses any key on the keyboard? All you had to do was ask:

Write-Host "Press any key to continue ..."

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

Write-Host
Write-Host "A"
Write-Host "B"
Write-Host "C"

So what are we doing in this script? Well, in the first line we’re simply displaying the ubiquitous prompt “Press any key to continue …”; that part should be pretty straightforward (and mundane). Far more interesting is what happens in line 2:

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

In this line we’re using PowerShell’s automatic variable $host (which is actually an instance of the .NET Framework class System.Management.Automation.Host) and the ReadKey method. (Which is actually a method of the RawUI property, which is a property of the UI property, which is a property of $host. And the leg bone’s connected to the knee bone, the knee bone’s connected to the ankle bone, the ….) The ReadKey method enables us to get information about the key that has just been pressed. Of course, in this case the only information we care about is the fact that a key has been pressed. Therefore, we pass ReadKey two parameters:

NoEcho. This prevents any information from appearing on screen when the user presses a key. If you leave out this parameter the pressed key will be echoed back to the screen.

IncludeKeyDown. This tells the script to continue as soon as a key has been pressed; that means the script will continue even if the user presses and holds a key down. If you’d prefer to wait until the user has released the key, then use this parameter instead: IncludeKeyUp.

There’s one more parameter that we can add to the ReadKey method: AllowCtrlC. In Windows PowerShell, pressing Ctrl+C typically causes the script to terminate. If you add the AllowCtrlC parameter to the ReadKey method, however, the user can choose to press Ctrl+C instead of pressing any other key. If they do that, the script will not terminate, but instead continue on as if the user had pressed any other key on the keyboard. (But only in conjunction with the ReadKey method. If the user presses Ctrl+C somewhere else the script will terminate.)

Note. So why would you want to do that? Good question. If nothing else, however, it does prevent the user from pressing Ctrl+C and terminating your script at that point.

Notice, too that we assign the result of the ReadKey method to the variable $x. That also helps prevent anything from appearing onscreen when the user presses a key. Remove $x = from the command and you’ll see what we mean; you’ll see something like this:

        VirtualKeyCode       Character        ControlKeyState         KeyDown
        --------------       ---------        ---------------         -------
                    88               x                      0            True

Ever hear the expression “too much information”? That’s too much information.

The rest of the script simply writes some information to the screen, just to prove that the script really did pause and continue. When you run this script your screen should first look like this:

PS C:\Scripts> c:\scripts\test.ps1
Press any key to continue ...

And then, after you press any key on the keyboard, the screen should look like this:

PS C:\Scripts> c:\scripts\test.ps1
Press any key to continue ...

A
B
C

Pretty cool, huh? Next week we’ll show you another nifty little trick for working with – and controlling – user input. See you then!