Waiting for user input with a timeout

后端 未结 4 1393
北海茫月
北海茫月 2020-11-28 15:36

I have searched but apparently my google foo is weak. What I need is a way to prompt for user input in the console and have the request time out after a period of time and c

相关标签:
4条回答
  • 2020-11-28 16:07

    Found something here:

    $counter = 0
    while(!$Host.UI.RawUI.KeyAvailable -and ($counter++ -lt 600))
    {
          [Threading.Thread]::Sleep( 1000 )
    }
    
    0 讨论(0)
  • 2020-11-28 16:12

    It's quite old now but how I solved it based on the same KeyAvailable method is here:

    https://gist.github.com/nathanchere/704920a4a43f06f4f0d2

    It waits for x seconds, displaying a . for each second that elapses up to the maximum wait time. If a key is pressed it returns $true, otherwise $false.

    Function TimedPrompt($prompt,$secondsToWait){   
        Write-Host -NoNewline $prompt
        $secondsCounter = 0
        $subCounter = 0
        While ( (!$host.ui.rawui.KeyAvailable) -and ($count -lt $secondsToWait) ){
            start-sleep -m 10
            $subCounter = $subCounter + 10
            if($subCounter -eq 1000)
            {
                $secondsCounter++
                $subCounter = 0
                Write-Host -NoNewline "."
            }       
            If ($secondsCounter -eq $secondsToWait) { 
                Write-Host "`r`n"
                return $false;
            }
        }
        Write-Host "`r`n"
        return $true;
    }
    

    And to use:

    $val = TimedPrompt "Press key to cancel restore; will begin in 3 seconds" 3
    Write-Host $val
    
    0 讨论(0)
  • 2020-11-28 16:13

    For people who are looking for a modern age solution with an additional constraint for exiting a PowerShell script on a pre-defined key press, the following solution might help you:

    Write-Host ("PowerShell Script to run a loop and exit on pressing 'q'!")
    $count=0
    $sleepTimer=500 #in milliseconds
    $QuitKey=81 #Character code for 'q' key.
    while($count -le 100)
    {
        if($host.UI.RawUI.KeyAvailable) {
            $key = $host.ui.RawUI.ReadKey("NoEcho,IncludeKeyUp")
            if($key.VirtualKeyCode -eq $QuitKey) {
                #For Key Combination: eg., press 'LeftCtrl + q' to quit.
                #Use condition: (($key.VirtualKeyCode -eq $Qkey) -and ($key.ControlKeyState -match "LeftCtrlPressed"))
                Write-Host -ForegroundColor Yellow ("'q' is pressed! Stopping the script now.")
                break
            }
        }
        #Do your operations
        $count++
        Write-Host ("Count Incremented to - {0}" -f $count)
        Write-Host ("Press 'q' to stop the script!")
        Start-Sleep -m $sleepTimer
    }
    Write-Host -ForegroundColor Green ("The script has stopped.")
    

    Sample script output:

    Refer Microsoft document on key states for handling more combinations.

    Credits: Technet Link

    0 讨论(0)
  • 2020-11-28 16:19

    Here is a keystroke utility function that accepts:

    • Validation character set (as a 1-character regex).
    • Optional message
    • Optional timeout in seconds

    Only matching keystrokes are reflected to the screen.

    Usage:

    $key = GetKeyPress '[ynq]' "Run step X ([y]/n/q)?" 5
    
    if ($key -eq $null)
    {
        Write-Host "No key was pressed.";
    }
    else
    {
        Write-Host "The key was '$($key)'."
    }
    

    Implementation:

    Function GetKeyPress([string]$regexPattern='[ynq]', [string]$message=$null, [int]$timeOutSeconds=0)
    {
        $key = $null
    
        $Host.UI.RawUI.FlushInputBuffer() 
    
        if (![string]::IsNullOrEmpty($message))
        {
            Write-Host -NoNewLine $message
        }
    
        $counter = $timeOutSeconds * 1000 / 250
        while($key -eq $null -and ($timeOutSeconds -eq 0 -or $counter-- -gt 0))
        {
            if (($timeOutSeconds -eq 0) -or $Host.UI.RawUI.KeyAvailable)
            {                       
                $key_ = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp")
                if ($key_.KeyDown -and $key_.Character -match $regexPattern)
                {
                    $key = $key_                    
                }
            }
            else
            {
                Start-Sleep -m 250  # Milliseconds
            }
        }                       
    
        if (-not ($key -eq $null))
        {
            Write-Host -NoNewLine "$($key.Character)" 
        }
    
        if (![string]::IsNullOrEmpty($message))
        {
            Write-Host "" # newline
        }       
    
        return $(if ($key -eq $null) {$null} else {$key.Character})
    }
    
    0 讨论(0)
提交回复
热议问题