PowerShell Limit Keys Accepted By Pause Script

1

Putting the following lines at the end of a PowerShell script has the following functionality:

  if($Host.Name -eq "ConsoleHost")
  {
    Write-Host "Press any key to continue..." -NoNewline
    $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null
  }
  1. If I run the script by right clicking on it, going to "Run with PowerShell," then the console window stays open for me until I press any key to continue.
  2. If I already have a PowerShell window open and I run the script from within this window, then although the "Press any key to continue" text still appears, I don't actually have to press anything to continue; it does this on its own. Hence, I can immediately run something else afterward.

I like this behavior, but I would prefer to limit it to a specific subset of keys (or even just a single key, such as the enter key), if possible. Using read-host doesn't work then I still have to enter input even when running from another PowerShell window; the goal is to simply stop the window from closing when I run it from the context menu. I shouldn't have to input anything when running from an already-existing PowerShell console.

Basically, I like the functionality of the code I have above, but I want to limit the keys it applies to.

Is it possible to achieve this? If so, how?

ereHsaWyhsipS

Posted 2018-07-17T22:50:18.350

Reputation: 403

Answers

0

As for this...

the goal is to simply stop the window from closing when I run it from the context menu

Of we all know that the reason this happens is that the context menu is just running powershell.exe and your script is a argument. So, it's supposed to close. You cannot do what you are after from the context menu without changing the way the context menu executes the call to the script host.

Sure you can go into the registry and hack at it to change that. However, to quickly deal with at least this close window on right click a .ps1, without reg hacking. Try this.

1 - Create a new desktop shortcut and place the below in the Target box.

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -noexit

2 - Give the Shortcut name PowerShell, or whatever

3 - Copy it to your SendTo folder: C:\Users\YourUserName\AppData\Roaming\Microsoft\Windows\SendTo

Right click your script and select SendTo, then select your shortcut.

Sure, it's one more click, but very simple to implement vs writing additional stuff.

Like the Taskbar, you can virtually put whatever you want in the SendTo folder to deal with a file type you'd like to work on / with / run.

As for this...

I would prefer to limit it to a specific subset of keys (or even just a single key, such as the enter key)

I am honestly not sure of the point (as you'd have to change the message and tell the user what key to press, since you are changing the default), I am sure you have your reasons, but that of course will require a bit more work and I'd have to toy with it first.

postanote

Posted 2018-07-17T22:50:18.350

Reputation: 1 783

0

Here's how I get Readkey to limit its input.

In the Function, there is an array of valid characters that the code checks against with the ($ValidCHARs -match $Response.Character) condition. If it does not match, then it will ignore the input.

This does not yet deal with Ctrl, Alt, Shift and the such. If you need that, comment below on your suggestion and I'll add it to this function.

Function Keyboard_Input { # KeyMode1 - One keystroke only, No Enter Required (Uses $Host.UI.RawUI.ReadKey)

    [array]$ValidCHARs = @( #Change these entries to allow more characters
    "A"
    "C"
    "D"
    "E"
    "J"
    "L"
    "M"
    "N"
    "P"
    "S"
    "T"
    "V"
    "0"
    )

    Write-Host "You must type one of the following: ";$ValidCHARS -join ","
    Write-Host ""
    Write-Host "Please press a key to make your selection..."

    $Host.UI.RawUI.FlushInputBuffer() #Needed to get a whole new keystroke entry

    DO {[array]$Response = $Host.UI.RawUI.ReadKey("IncludeKeyDown,NoEcho")} UNTIL ($ValidChars -match $Response.Character)

    Write-Host ""
    Start-Sleep -Milliseconds 250
    Write-Host "################################################"
    Write-Host -no "Attributes of Response are: " -F Red;Get-Variable -Name Response | Select *;Start-Sleep -Milliseconds 500
    Write-Host "################################################"
    Write-Host "The Response Record Values are: " -F Red;$Response
    pause
}

Keyboard_Input
pause

Inventologist

Posted 2018-07-17T22:50:18.350

Reputation: 1

Hi Scott, the timeout had nothing to do with the solution, I just figured it would be a neat thing to leave in there. I apologize that it confused the answer to the question. I have reworked the entire function to be free-standing without the timeout on the input. I've also added a couple of lines to give some output on the key that you do hit so that you can get the extra info like: the Character, VirtualKeyCode and ControlKeyState. – Inventologist – 2019-02-18T23:12:11.143