Цель:
Я хочу асинхронно запускать индикатор выполнения (который показывает прошедшее время/расчетное время) в ожидании молчащих установок. Например,Как запустить индикатор выполнения асинхронно при выполнении автоматической установки?
RunWithProgressBar "cmd /c """" /Wait ""Setup.exe""" $(New-Timespan -Minutes 5)
Ближайший я Произошел:
## Functions
function global:BottleOfBeer {
$beer = $args[0]
if ($beer -eq 1) {
echo "$beer beer on the wall.";
} elseif ($beer -eq 0) {
echo "No beer left on the wall!";
} else {
echo "$beer beers left on the wall.";
}
sleep 1
}
function global:BeersOnTheWall {
$NumBeers = $args[0]
for ($i=$NumBeers; $i -ge 0; $i--) {
BottleOfBeer $i
}
}
function global:Install {
cmd /c @"
"AutoHotkey112306_Install.exe" /S /D="%cd%"
"@
}
function global:Uninstall {
cmd /c start "" /wait "Installer.ahk" /Uninstall
}
####START Progress Bar Stuff
function global:DisplayProgress {
$display = $args[0]
Write-Progress -Activity "Running..." -Status "$display"
}
function global:FormatDisplay {
$StartTime = $args[0]
$RunningTime = ($args[1]).Elapsed
$EstimatedTime = $args[2]
$RunningTimeDisplay = $([string]::Format("{0:d2}:{1:d2}:{2:d2}",
$RunningTime.hours,
$RunningTime.minutes,
$RunningTime.seconds))
$EstimatedEnd = $StartTime + $EstimatedTime
return $([string]::Format("(Start: {0}) (Elapsed/Estimated: {1}/{2}) (EstimatedEnd: {3})",
$StartTime.ToShortTimeString(),
$RunningTimeDisplay,
$EstimatedTime,
$EstimatedEnd.ToShortTimeString()))
}
function global:TearDownProgressBar {
$job = $args[0]
$event = $args[1]
$job,$event | Stop-Job -PassThru | Remove-Job #stop the job and event listener
Write-Progress -Activity "Working..." -Completed -Status "All done."
}
function RunWithProgressBar {
$Payload = $args[0]
$EstimatedTime = $args[1]
$global:StartTime = Get-Date
$global:RunningTime = [System.Diagnostics.Stopwatch]::StartNew()
$global:EstimatedTime = $EstimatedTime
$progressTask = {
while($true) {
Register-EngineEvent -SourceIdentifier MyNewMessage -Forward
$null = New-Event -SourceIdentifier MyNewMessage -MessageData "Pingback from job."
Start-Sleep -Seconds 1
}
}
$job = Start-Job -ScriptBlock $progressTask
$event = Register-EngineEvent -SourceIdentifier MyNewMessage -Action {
DisplayProgress $(FormatDisplay $global:StartTime $global:RunningTime $global:EstimatedTime)
}
try {
sleep 1
Invoke-Expression $Payload
} finally {
TearDownProgressBar $job $event
}
}
####END Progress Bar Stuff
## MAIN
RunWithProgressBar "BeersOnTheWall 2" $(New-Timespan -Seconds 3)
RunWithProgressBar "Install" $(New-Timespan -Seconds 30)
RunWithProgressBar "Uninstall" $(New-Timespan -Seconds 5)
RunWithProgressBar "BeersOnTheWall 2" $(New-Timespan -Seconds 3)
Проблему
Хотя выше реализация работает как задумано, когда полезная нагрузка аргумент RunWithProgressBar
является установить событие, которое обновляет индикатор выполнения перестает запускаться.
Что я ищу:
Как изменить свою текущую реализацию для обновления индикатор выполнения каждую секунду, даже во время выполнения установки?
По какой мере вы хотите обновить индикатор выполнения? Система не может заглянуть в будущее, чтобы увидеть, когда будет завершена установка, и не узнает, какие элементы будет обрабатываться установщиком. –
Вы принимаете решение как человек, основанный на том, как долго вы думаете, что это займет. Ex. Notepadd ++ должен установить в течение 5 минут. Этот скрипт будет запущен на нескольких машинах того же типа; разумные оценки легко найти с первого запуска. –