How to Properly Pause a PowerShell Script

When I first learned about PowerShell, I immediately wanted to convert my batch files into PowerShell scripts and then enhance them with additional features. When I started that process, I quickly learned that PowerShell didn’t have anything equivalent to cmd.exe’s “Pause” command. I looked for a solution online and found the Microsoft TechNet article Windows PowerShell Tip: Press Any Key to Continue. This is the solution recommended by the article:

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

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

However, the above solution has two things wrong with it:

  • It doesn’t work from within Windows PowerShell ISE
  • Unlike cmd.exe’s “Pause” command, pressing keys like Ctrl and Alt causes the script to continue

To fix these two issues, I decided to write my own “Pause” function:

Function Pause ($Message = "Press any key to continue . . . ") {
	If ($psISE) {
		# The "ReadKey" functionality is not supported in Windows PowerShell ISE.

		$Shell = New-Object -ComObject "WScript.Shell"
		$Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)

		Return
	}

	Write-Host -NoNewline $Message

	$Ignore =
		16,  # Shift (left or right)
		17,  # Ctrl (left or right)
		18,  # Alt (left or right)
		20,  # Caps lock
		91,  # Windows key (left)
		92,  # Windows key (right)
		93,  # Menu key
		144, # Num lock
		145, # Scroll lock
		166, # Back
		167, # Forward
		168, # Refresh
		169, # Stop
		170, # Search
		171, # Favorites
		172, # Start/Home
		173, # Mute
		174, # Volume Down
		175, # Volume Up
		176, # Next Track
		177, # Previous Track
		178, # Stop Media
		179, # Play
		180, # Mail
		181, # Select Media
		182, # Application 1
		183  # Application 2

	While ($KeyInfo.VirtualKeyCode -Eq $Null -Or $Ignore -Contains $KeyInfo.VirtualKeyCode) {
		$KeyInfo = $Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown")
	}

	Write-Host
}

Here’s the minified version:

Function Pause($M="Press any key to continue . . . "){If($psISE){$S=New-Object -ComObject "WScript.Shell";$B=$S.Popup("Click OK to continue.",0,"Script Paused",0);Return};Write-Host -NoNewline $M;$I=16,17,18,20,91,92,93,144,145,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183;While($K.VirtualKeyCode -Eq $Null -Or $I -Contains $K.VirtualKeyCode){$K=$Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")};Write-Host}
About these ads

11 comments

  1. Other than the alternate codepath for the ISE, I think:

    [void][System.Console]::ReadKey($FALSE)

    is similar to the ‘pause’ mechanics.

      1. Thank you! You are correct about your code being similar to cmd.exe’s “Pause” mechanics. Although your code is certainly much leaner than the code I have in this blog post, it only ignores *some* of the same keys as cmd.exe’s “Pause” command. One notable key your code doesn’t ignore is the Windows key.

  2. Your loop would work easier and better like this:

    DO {
    $PressedKey = $Host.UI.RawUI.ReadKey(“NoEcho, IncludeKeyDown”)
    } While ($Ignore -Contains $PressedKey.VirtualKeyCode)

  3. For starters, read-host “Click Enter to continue ” ?
    has no button that states Enter. It has OK and Cancel. Cancel will end up stopping your script. The verbage ‘Press any key’ was always a misnomer in that not every key caused the intended action to take place. However, there are plenty of keys that did. The action of clicking OK is very different than pressing any key that was sensed. And last, read-host pops up a box that may not fit with the authors design of running on a command-prompt type of environment.

    Remember, your repliy should answer the author’s request more than steer them to do what you want to do. When someone does not have an answer and wants to suggest their alternative they should declare that is what they are doing.

  4. Lots of googling finally led me to
    # The “ReadKey” functionality is not supported in Windows PowerShell ISE.

    Ah, now I understand. Your pause function is exactly what I needed!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s