与在脚本中使用pause
不同,让脚本在设定的时间后自动退出对我来说很有用,这对我来说特别有用,因为这些脚本可以交互运行,或者作为Start-Process -WindowStyle Hidden
的后台任务运行,pause
意味着进程可能会永远挂起,但使用计时器,即使它在后台,它将超时。通过以下问题向我提供了此解决方案:PowerShell, break out of a timer with custom keypress
$t = 8; Write-Host "Exiting in $t seconds (press any key to exit now)" -NoNewLine
for ($i=0; $i -le $t; $i++) {
Start-Sleep 1; Write-Host -NoNewLine "."
if ([Console]::KeyAvailable) {
$key = [Console]::ReadKey($true).Key
if ($key) { break }
}
}
但是,如果我在后台使用Start-Process -WindowStyle Hidden
运行此命令,PowerShell会由于[Console]::KeyAvailable
而生成错误,因为在后台运行时没有可用的控制台。
Cannot see if a key has been pressed when either application does not have a
console or when console input has been redirected from a file. Try
Console.In.Peek.
At C:\Users\Boss\Install Chrome.ps1:36 char:78
+ ... ep 1; Write-Host -NoNewLine "."; if ([Console]::KeyAvailable) { $key ...
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidOperationExcept
ion
+ FullyQualifiedErrorId : System.InvalidOperationException
·有没有什么方法可以调整我的代码,使它在后台运行时不会产生错误,同时在交互运行时仍然保留“按任意键立即退出”选项?
·Try Console.In.Peek
是什么意思?
2条答案
按热度按时间g2ieeal71#
Start-Process
**:powershell.exe
)时, 始终 * 分配控制台-即使它是 * 隐藏的 *(-WindowStyle Hidden
)-RedirectStandardInput
,否则控制台的stdin流([Console]::In
)* 不 * 重定向,如[Console]::IsInputRedirected
返回$false
所示。[Console]::KeyAvailable
将始终返回$false
,并且整个超时周期将过去。Start-Job
**的问题:[Console]::KeyAvailable
会导致您看到的语句终止错误,假定错误消息中提到的原因之一适用:* 标准输入被重定向 *(但控制台确实存在)。只需在
[Console]::IsInputRedirected
返回$false
的条件下使用[Console]::KeyAvailable
:Start-ThreadJob
**,它 * 随PowerShell(Core)7 +* 一起提供,在 * Windows PowerShell * 中,可以 * 按需安装 *,例如,Install-Module ThreadJob -Scope CurrentUser
:线程作业(如果可用)通常比常规的、基于子进程的后台作业更可取,因为线程作业更快、重量更轻。
由于 * stdin * 的使用仅适用于 * 进程间 * 通信,因此
[Console]::KeyAvailable
不会导致线程作业中的错误,并且-值得推荐的是-仅当手头的线程是 * 前台 * 线程时才注意击键。rkue9o1l2#
使用
Runspace
而不是Start-Process
。运行空间可以与PSHost
相关联,因此您将看到两个好处,输出到控制台和按任意键取消脚本的能力。