Esperando la entrada del usuario con un tiempo de espera
-
02-07-2019 - |
Pregunta
He buscado pero aparentemente mi google foo es débil. Lo que necesito es una forma de solicitar la entrada del usuario en la consola y tener el tiempo de espera de la solicitud después de un período de tiempo y continuar ejecutando el script si no entra ninguna entrada. Por lo que puedo decir, Read-Host no proporciona esto funcionalidad Ni $ host.UI.PromptForChoice () ni $ host.UI.RawUI.ReadKey (). Gracias de antemano por cualquier puntero.
EDITAR: Muchas gracias a Lars Truijens por encontrar la respuesta. Tomé el código que él señaló y lo encapsulé en una función. Tenga en cuenta que la forma en que lo he implementado significa que podría haber hasta un segundo de retraso entre el momento en que el usuario toca una tecla y la continuación de la ejecución del script.
function Pause-Host
{
param(
$Delay = 1
)
$counter = 0;
While(!$host.UI.RawUI.KeyAvailable -and ($counter++ -lt $Delay))
{
[Threading.Thread]::Sleep(1000)
}
}
Solución
Encontré algo aquí :
$counter = 0
while(!$Host.UI.RawUI.KeyAvailable -and ($counter++ -lt 600))
{
[Threading.Thread]::Sleep( 1000 )
}
Otros consejos
Es bastante antiguo ahora, pero cómo lo resolví con el mismo método KeyAvailable está aquí:
https://gist.github.com/nathanchere/704920a4a43f06f4f0d2
Espera x segundos, mostrando un .
por cada segundo que transcurre hasta el tiempo máximo de espera. Si se presiona una tecla, devuelve $ true
; de lo contrario, $ 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;
}
Y para usar:
$val = TimedPrompt "Press key to cancel restore; will begin in 3 seconds" 3
Write-Host $val
Para las personas que buscan una solución de la era moderna con una restricción adicional para salir de un script de PowerShell al presionar una tecla predefinida, la siguiente solución podría ayudarlo:
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.")
Consulte Documento de Microsoft sobre estados clave para manejar más combinaciones.
Créditos: Enlace de Technet
Aquí hay una función de utilidad de pulsación de tecla que acepta:
- Conjunto de caracteres de validación (como una expresión regular de 1 carácter).
- Mensaje opcional
- Tiempo de espera opcional en segundos
Solo las pulsaciones de teclas coincidentes se reflejan en la pantalla.
Uso:
$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)'."
}
Implementación:
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})
}