Ожидание ввода пользователя с таймаутом - PullRequest
19 голосов
/ 29 сентября 2008

Я искал, но, видимо, мой Google Foo слаб. Что мне нужно, так это способ запрашивать ввод данных пользователем в консоли и иметь время ожидания запроса через некоторое время и продолжать выполнение сценария, если ввод не поступает. Насколько я могу судить, Read-Host этого не обеспечивает функциональность. Ни $ host.UI.PromptForChoice (), ни $ host.UI.RawUI.ReadKey () не работают. Заранее спасибо за любые указатели.

РЕДАКТИРОВАТЬ: Большое спасибо Lars Truijens за поиск ответа. Я взял код, который он указал, и заключил его в функцию. Обратите внимание, что способ, который я реализовал, означает, что может быть до одной секунды задержки между моментом, когда пользователь нажимает клавишу, и продолжением выполнения скрипта.

function Pause-Host
{
    param(
            $Delay = 1
         )
    $counter = 0;
    While(!$host.UI.RawUI.KeyAvailable -and ($counter++ -lt $Delay))
    {
        [Threading.Thread]::Sleep(1000)
    }
}

Ответы [ 4 ]

16 голосов
/ 29 сентября 2008

Нашли что-то здесь :

$counter = 0
while(!$Host.UI.RawUI.KeyAvailable -and ($counter++ -lt 600))
{
      [Threading.Thread]::Sleep( 1000 )
}
5 голосов
/ 30 марта 2015

Сейчас он довольно старый, но как я решил его, используя тот же метод KeyAvailable, можно узнать здесь:

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

Он ждет x секунд, отображая . каждую секунду, которая истекает до максимального времени ожидания. Если клавиша нажата, она возвращает $true, в противном случае $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;
}

И использовать:

$val = TimedPrompt "Press key to cancel restore; will begin in 3 seconds" 3
Write-Host $val
1 голос
/ 10 мая 2018

Для людей, которые ищут современное решение с дополнительным ограничением для выхода из сценария PowerShell при предварительно определенном нажатии клавиши, вам может помочь следующее решение:

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.")

Пример вывода скрипта: enter image description here

См. Документ Microsoft о состояниях клавиш для обработки большего количества комбинаций.

Кредиты: Technet Link

0 голосов
/ 28 сентября 2018

Вот вспомогательная функция нажатия клавиш, которая принимает:

  • Набор символов для проверки (как регулярное выражение из 1 символа).
  • Необязательное сообщение
  • Дополнительное время ожидания в секундах

Только соответствующие нажатия клавиш отображаются на экране.

Использование:

$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)'."
}

Реализация:

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})
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...