Почему команда в ScriptBlock не работает? - PullRequest
0 голосов
/ 07 июня 2019

Я хочу измерить истекшее время из командлета

Invoke-ASCmd

Я использую его следующим образом

$elapsedTime = [system.diagnostics.stopwatch]::StartNew()
$j = Start-Job -ScriptBlock {
    Invoke-ASCmd –InputFile $XMLF -Server "$Server[-1]" >$output_file
}
do {
    write-progress -activity "Syncing..." -status "$([string]::Format("Time Elapsed: {0:d2}:{1:d2}:{2:d2}", $elapsedTime.Elapsed.hours, $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds))" 
    #-percentcomplete ($_/10);
    Start-Sleep -milliseconds 250
} while ($j.State -eq 'Running')
Receive-Job -Job $j

$elapsedTime.stop()

Однако все, что я вижу на консоли, - это мигающий синий индикатор прогрессапанель, которая, кажется, даже не затягивает время ... и, честно говоря, я даже не думаю, что блок скриптов вообще выполняется (командлет Invoke)

почему это так?

image

и кажется, что он длится 1 секунду

image2

Я знаю, что скрипт-блок неработает, потому что синхронизация должна занимать не менее 20 секунд, поэтому что-то не так

Кроме того, я хотел бы получить процент (анимация кругов / prgress), это не работает

-percentcomplete ($_/10);

И последнее, я хотел бы сохранить окончательное прошедшее время в переменной $FinalTime. Буду ли я делать это внутри цикла или снаружи?

Я объединяю эти два ответа здесь и изменяю для своих нужд:

https://stackoverflow.com/a/9813370/8397835

https://stackoverflow.com/a/8468024/8397835

1 Ответ

3 голосов
/ 07 июня 2019

Да, процесс идет быстро, потому что PowerShell требуется 1 секунда для загрузки модуля, прежде чем произойдет ошибка. Мы можем увидеть сообщение об ошибке с Receive-Job:

PS C:\> Receive-Job $j
InputFile "" not found
    + CategoryInfo          : InvalidData: (:) [Invoke-ASCmd], FileNotFoundException
    + FullyQualifiedErrorId : DataValidation,Microsoft.AnalysisServices.PowerShell.Cmdlets.ExecuteScriptCommand
    + PSComputerName        : localhost

InputFile "" not found указывает, что переменные были пустыми. Они пусты, потому что вы не можете ссылаться на переменные непосредственно внутри блока скриптов. Используя Start-Job, вы должны передать его в блок скриптов в качестве аргумента и получить его в качестве параметра внутри блока скриптов. Примерно так:

$j = Start-Job -Arg $XMLF, $Server, $output_file -ScriptBlock {
    Param($XMLF, $Server, $output_file)
    Invoke-ASCmd –InputFile $XMLF -Server "$Server" >$output_file
}

Что касается прогресса, так как не существует «прямого» способа измерить, насколько далеко продвинется прогресс до 100%, мы «подделываем его». Поскольку мы знаем, что выполнение занимает около 20 секунд, мы просто выполняем некоторые вычисления с использованием времени от 0 до 20 в качестве прогресса от 0 до 100:

[Math]::Min(100*($elapsedTime.Elapsed.Seconds / 20),100)

В основном используйте $elapsedTime от 0 до 100 процентов в течение 20 секунд. Эти 20 секунд можно изменить на любое число, близкое к приблизительному времени выполнения. Используя [Math]::Min, мы гарантируем, что если это займет больше 20 секунд, прогресс будет отображаться на 100 процентов, но статус будет продолжать показывать время. Так бы это выглядело так:

do {
    write-progress -activity "Syncing..." -status "$($elapsedTime.Elapsed.ToString())" -percentcomplete ([Math]::Min(100*($elapsedTime.Elapsed.Seconds / 20),100));
    Start-Sleep -Milliseconds 250
} while ($j.State -eq 'Running')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...