Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure a timeout for Read-Host in PowerShell

Like I said, this code works in PowerShell version 2, but not in PowerShell version 5.

function wait
      {
       $compte = 0
        Write-Host  "To continue installation and ignore configuration warnings      type [y], type any key to abort"
          While(-not $Host.UI.RawUI.KeyAvailable -and ($compte -le 20))
         {
          $compte++
          Start-Sleep -s 1
          }
           if ($compte -ge 20)
           {
        Write-Host "Installation aborted..."
           break
           }
        else
            {
        $key = $host.ui.rawui.readkey("NoEcho,IncludeKeyup")
            }
         if ($key.character -eq "y")
            {Write-Host "Ignoring configuration warnings..."}
         else 
            {Write-Host "Installation aborted..." 
            }}
like image 562
h.s Avatar asked May 02 '17 08:05

h.s


People also ask

What is read host in PowerShell?

The Read-Host cmdlet reads a line of input from the console (stdin). You can use it to prompt a user for input. Because you can save the input as a secure string, you can use this cmdlet to prompt users for secure data, such as passwords. Note. Read-Host has a limit of 1022 characters it can accept as input from a user ...


2 Answers

The official documentation or Read-Host -? will tell that it's not possible to use Read-Host in that manner. There is no possible parameter to tell it to run with some kind of timeout.

But there are various other questions detailing how to do this in PowerShell (usually utilizing C#).

The idea seems to be to check whenever the user pressed a key using $Host.UI.RawUI.KeyAvailable and check that for the duration of your timeout.

A simple working example could be the following:

$secondsRunning = 0;
Write-Output "Press any key to abort the following wait time."
while( (-not $Host.UI.RawUI.KeyAvailable) -and ($secondsRunning -lt 5) ){
    Write-Host ("Waiting for: " + (5-$secondsRunning))
    Start-Sleep -Seconds 1
    $secondsRunning++
}

You could use $host.UI.RawUI.ReadKey to get the key that was pressed. This solution probably would not be acceptable if you need more complex input than a simple button press. See also:

  • Windows PowerShell Tip of the Week - Pausing a Script Until the User Presses a Key
  • PowerTip: Use PowerShell to Wait for a Key Press (Hey, Scripting Guy!)
like image 141
Seth Avatar answered Nov 15 '22 04:11

Seth


Seth, thank you for your solution. I expanded on the example you provided and wanted to give that back to the community.

The use case is a bit different here - I have a loop checking if an array of VMs can be migrated and if there are any failures to that check the operator can either remediate those until the checks clear or they can opt to "GO" and have those failing VMs excluded from the operation. If something other than GO is typed state remains within the loop.

One downside to this is if the operator inadvertently presses a key the script will be blocked by Read-Host and may not be immediately noticed. If that's a problem for anyone I'm sure they can hack around that ;-)

Write-Host "Verifying all VMs have RelocateVM_Task enabled..."
Do {
    $vms_pivoting = $ph_vms | Where-Object{'RelocateVM_Task' -in $_.ExtensionData.DisabledMethod}
    if ($vms_pivoting){
        Write-Host -ForegroundColor:Red ("Some VMs in phase have method RelocateVM_Task disabled.")
        $vms_pivoting | Select-Object Name, PowerState | Format-Table -AutoSize
        Write-Host -ForegroundColor:Yellow "Waiting until this is resolved -or- type GO to continue without these VMs:" -NoNewline
        $secs = 0
        While ((-not $Host.UI.RawUI.KeyAvailable) -and ($secs -lt 15)){
            Start-Sleep -Seconds 1
            $secs++
        }
        if ($Host.UI.RawUI.KeyAvailable){
            $input = Read-Host
            Write-Host ""
            if ($input -eq 'GO'){ 
                Write-Host -ForegroundColor:Yellow "NOTICE: User prompted to continue migration without the blocked VM(s)"
                Write-Host -ForegroundColor:Yellow "Removing the following VMs from the migration list"
                $ph_vms = $ph_vms | ?{$_ -notin $vms_pivoting} | Sort-Object -Property Name
            }
        }
    } else {
        Write-Host -ForegroundColor:Green "Verified all VMs have RelocateVM_Task method enabled."
    }
} Until(($vms_pivoting).Count -eq 0)
like image 32
meyeaard Avatar answered Nov 15 '22 04:11

meyeaard