I also have this problem before, now I have a perfect solution I think.
Here is my PowerShell version info:
Name Value
---- -----
PSVersion 5.1.19041.2673
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.2673
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Here is my Read-Host with timeout implement code:
Function Read-HostWithTimeout {
param(
[string]$Prompt = "Input Text: ",
[System.ConsoleColor]$PromptBackGroundColor = $Host.UI.RawUI.BackgroundColor,
[System.ConsoleColor]$PromptForeGroundColor = $Host.UI.RawUI.ForegroundColor,
[int]$Timeout = 5000,
[string]$TimeoutHint = "Timeout",
[System.ConsoleColor]$HintBackgroundColor = $Host.UI.RawUI.BackgroundColor,
[System.ConsoleColor]$HintForeGroundColor = [System.ConsoleColor]::Yellow
)
Write-Host $Prompt -ForegroundColor $PromptForeGroundColor -BackgroundColor $PromptBackGroundColor -NoNewline
$res = try {
$ErrorActionPreference = 'Stop'
powershell.exe -Command {
param($Timeout)
$InitialSessionState = [initialsessionstate]::CreateDefault()
$InitialSessionState.Variables.Add(
[System.Management.Automation.Runspaces.SessionStateVariableEntry]::new(
"ThreadContext",
@{Host = $Host },
"share host between threads"
)
)
$PSThread = [powershell]::Create($InitialSessionState)
$null = $PSThread.AddScript{
$ThreadContext.Host.UI.ReadLine()
}
$Job = $PSThread.BeginInvoke()
if (-not $Job.AsyncWaitHandle.WaitOne($Timeout)) {
Get-Process -Id $PID | Stop-Process
}
else {
return $PSThread.EndInvoke($Job)
}
} -args $Timeout
}
catch {
Write-Host $TimeoutHint -ForegroundColor $HintForeGroundColor -BackgroundColor $HintBackGroundColor
}
return $res
}
you can use this function like this:
$UserInput = Read-HostWithTimeout -Timeout 1000
$UserInput // outuput input sting
If user input a string, $UserInput
is what user input. If user input timeout, it will return $null
, nothing output.