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}
Advertisements
Other than the alternate codepath for the ISE, I think:
[void][System.Console]::ReadKey($FALSE)
is similar to the ‘pause’ mechanics.
That should say $TRUE to hide the console echo.
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.
Your loop would work easier and better like this:
DO {
$PressedKey = $Host.UI.RawUI.ReadKey(“NoEcho, IncludeKeyDown”)
} While ($Ignore -Contains $PressedKey.VirtualKeyCode)
Thanks for this. Very useful bit of code for leaving the output up on the screen to view
Hello,
What’s the difference with a simple : read-host “Click Enter to continue ” ??
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.
I don’t get a pop-up for “read-host “click enter to continue.” ether in the ISE, or right-click/Run With Powershell, or running . I just get text in the powershell window that says “click enter to continue.”
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!
“cmd /c pause” works for me
cleanest version on this page! +1 Ryan
that was all I needed +1
Thanks for the code…it helps!!!
I like to use the pause function just after a message. To cut down on typing, I made the message a parameter that defaults to “Press any key to continue…” only if nothing else is entered:
Function Pause {
Param([Parameter(ValueFromRemainingArguments=$true)][string]$M = “Press any key to continue . . . ” )
If($psISE){$S=New-Object -ComObject “WScript.Shell”;$B=$S.Popup(“Click OK to continue.”,0,”$M”,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
}
Thanks so very much! I am using the “minified” version because I need a script that shows output and allows for a nice break
Thanks Adam
Is there any easy way to change this form to add an extra button to exit when clicked and stop the script execution?