Ожидание ввода пользователя с таймаутом

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

Обновлено: Большое спасибо Ларсу Труидженсу за то, что он нашел ответ. Я взял код, который он указал, и инкапсулировал его в функцию. Обратите внимание, что способ, которым я это реализовал, означает, что между тем, когда пользователь нажимает клавишу, и продолжением выполнения скрипта может быть задержка до одной секунды.

function Pause-Host
{
    param(
            $Delay = 1
         )
    $counter = 0;
    While(!$host.UI.RawUI.KeyAvailable -and ($counter++ -lt $Delay))
    {
        [Threading.Thread]::Sleep(1000)
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
0
20 113
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

$counter = 0
while(!$Host.UI.RawUI.KeyAvailable -and ($counter++ -lt 600))
{
      [Threading.Thread]::Sleep( 1000 )
}

Большое Вам спасибо. Я склоняюсь перед твоим могущественным гугл-фу.

EBGreen 29.09.2008 23:50

В PowerShell 2 также есть командлет Start-Sleep.

Joey 06.04.2011 20:27

Сейчас он довольно старый, но вот как я решил его на основе того же метода 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

Проблема с вышесказанным заключается в том, что любое нажатие клавиши не «проглатывается». Чтобы проглотить его, вы можете положить перед окончательным возвратом следующее: $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

Martin Connell 22.02.2018 18:29

Небольшой совет, вам нужна только 1 переменная таймера внутри функции, вы можете обновить экран (хост записи), используя уравнение модуля. По сути, сохраните и переименуйте subCounter (в elapsedTime или что-то в этом роде), а затем вместо «if ($ subCounter -eq 1000)» вы можете сделать «if ($ elapsedTime% 1000 -eq 0)» И во втором, если бы у вас было умножить secondsToWait на 1000 (поскольку вы измеряете в мс) или просто измените проход в мс вместо секунд.

Michaël 06.05.2019 17:04

Если я использую $val = TimedPrompt "Press key to cancel restore; will begin in 3 seconds" 3 Write-Host $val более одного раза в скрипте, он не будет ждать второй раз.

David Gleba 07.03.2020 15:22

Для людей, которые ищут современное решение с дополнительным ограничением для выхода из сценария 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.")

Пример вывода скрипта:

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

Кредиты: Technet Link

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

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

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

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

$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})
}

Exception calling "FlushInputBuffer" with "0" argument(s): "The method or operation is not implemented." PSVersion = 5.1.17763.771

Ross Presser 26.02.2020 18:13

Ах, исключение случается только в PowerShell ISE. В прямом окне PS нормально. Похоже, необработанный пользовательский интерфейс вообще нельзя проверить в ISE, так что будьте осторожны.

Ross Presser 26.02.2020 18:21

Другие вопросы по теме