我一直在尋找在我的腳本中添加一個簡單的倒數計時器。我發現這個似乎可以解決問題并稍微修改它以僅顯示秒數,因為我不需要更多的東西。
當我運行它時,它會跳過倒計時的第二秒。例如,如果我 run Start-CountdownTimer -Seconds 10,輸出將是(出于演示目的將其拆分為單獨的行,因為它將在同一行上):
| Starting in 10s ...
/ Starting in 8s ...
- Starting in 7s ...
\ Starting in 6s ...
| Starting in 5s ...
/ Starting in 4s ...
- Starting in 3s ...
\ Starting in 2s ...
| Starting in 1s ...
/ Starting in 0s ...
有什么想法可以解決這個問題嗎?這是上面鏈接中的(稍微修改的)代碼:
Function Start-CountdownTimer{
param (
<#[int]$Days = 0,
[int]$Hours = 0,
[int]$Minutes = 0,#>
[int]$Seconds = 0,
[int]$TickLength = 1
)
$t = New-TimeSpan <#-Days $Days -Hours $Hours -Minutes $Minutes#> -Seconds $Seconds
$origpos = $host.UI.RawUI.CursorPosition
$spinner =@('|', '/', '-', '\')
$spinnerPos = 0
$remain = $t
$d =( get-date) $t
$remain = ($d - (get-date))
while ($remain.TotalSeconds -gt 0){
Write-Host (" {0} " -f $spinner[$spinnerPos%4]) -ForegroundColor White -NoNewline
write-Host (" Starting in {0:d1}s ..." -f $remain.Seconds)
$host.UI.RawUI.CursorPosition = $origpos
$spinnerPos = 1
Start-Sleep -seconds $TickLength
$remain = ($d - (get-date))
}
$host.UI.RawUI.CursorPosition = $origpos
}
uj5u.com熱心網友回復:
如果您想要一個永遠不會跳過倒計時步驟的解決方案- 代價是運行時間比指定的倒計時持續時間長一點(時間越長,持續時間越長) - 請參閱Santiago Squarzon 的有用答案。
如果您想要一個解決方案,它可以在系統負載較重的情況下跳過倒計時步驟,但仍然接近指定的倒計時持續時間,無論其長度如何,請參見下文。
正如Theo指出的那樣,您的實作有些低效,這增加了跳過步驟的風險。
下面是一個簡化的實作,它降低了跳過的風險,盡管在系統負載很重的情況下它仍然可能發生。
筆記:
該功能在 Windows PowerShell ISE中無法正常作業,但ISE 已過時并且一直有理由不使用它(底部);相比之下,該函式在 ISE 的繼任者Visual Studio Code及其PowerShell 擴展中確實有效
不是使用
$host.UI.RawUI,而是"`r"在每個倒計時步驟的開始處發出一個簡單的 CR ( )Write-Host -NoNewLine,這會導致游標回傳到行首并覆寫現有行。為避免行被覆寫時閃爍,臨時關閉游標,使用
[Console]::CursorVisible]嚴格來說,根據 PowerShell 對其已批準動詞的描述,您的函式應命名為
Invoke-CoutdownTimer,因為它是同步執行的,盡管該標準Start-Sleep同樣被錯誤命名 -有關討論,請參閱GitHub 檔案問題 #4474。
Function Start-CountdownTimer {
param (
[Parameter(Mandatory)]
[ValidateRange(0,999)]
[int] $Seconds,
[int] $SleepIntervalMilliSeconds = 1000
)
$spinner = '|', '/', '-', '\'
$spinnerPos = 0
[Console]::CursorVisible = $false
$dtEnd = [datetime]::UtcNow.AddSeconds($Seconds)
try {
while (($remainingSecs = ($dtEnd - [datetime]::UtcNow).TotalSeconds) -gt 0) {
Write-Host -NoNewline ("`r {0} " -f $spinner[$spinnerPos % 4]) -ForegroundColor White
Write-Host -NoNewLine (" Starting in {0,3}s ... " -f [Math]::Ceiling($remainingSecs))
Start-Sleep -Milliseconds ([Math]::Min($SleepIntervalMilliSeconds, $remainingSecs * 1000))
}
Write-Host
}
finally {
[Console]::CursorVisible = $true
}
}
uj5u.com熱心網友回復:
嗯,這應該是對你的改進function,也應該解決多跳一秒的問題。我個人不同意使用$host,Clear-Host而是會使用,因此該功能也與 PowerShell ISE 兼容,但您可以根據需要進行更改。
Function Start-CountdownTimer{
param(
[CmdletBinding(DefaultParameterSetName = 'Time')]
[parameter(ParameterSetName = 'Hours')]
[ValidateRange(1, [int]::MaxValue)]
[int]$Hours = 0,
[parameter(ParameterSetName = 'Minutes')]
[ValidateRange(1, [int]::MaxValue)]
[int]$Minutes = 0,
[parameter(ParameterSetName = 'Seconds', Position = 0)]
[ValidateRange(1, [int]::MaxValue)]
[int]$Seconds = 0
)
$now = [datetime]::Now
$spinner = @('|', '/', '-', '\')
$spinnerPos = 0
$origpos = $host.UI.RawUI.CursorPosition
$runTime = switch($PSBoundParameters.Keys)
{
Hours { $now.AddHours($PSBoundParameters[$PSBoundParameters.Keys]) }
Minutes { $now.AddMinutes($PSBoundParameters[$PSBoundParameters.Keys]) }
Seconds { $now.AddSeconds($PSBoundParameters[$PSBoundParameters.Keys]) }
}
$runTime = $runTime.TimeOfDay.TotalSeconds - $now.TimeOfDay.TotalSeconds
while($runTime)
{
Write-Host (" {0} " -f $spinner[$spinnerPos%4]) -NoNewline
Write-Host " Starting in ${runTime}s ..."
$host.UI.RawUI.CursorPosition = $origpos
$spinnerPos = 1
$runTime--
Start-Sleep -Seconds 1
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/346010.html
標籤:电源外壳
上一篇:獲取DNS腳本在報告中缺少輸出
