Назад | Перейти на главную страницу

Рабочий процесс Powershell: рабочий процесс был прерван действием завершения

У меня есть сценарий PowerShell, который запускает множество msdeploy одновременно на нескольких удаленных серверах с использованием рабочего процесса Powershell.

Все работает нормально, за исключением того, что в конце каждого цикла «Foreach -Parallel» я получаю следующее исключение:

Microsoft.PowerShell.Utility\Write-Error : The workflow was terminated by a Terminate activity.
At Execute-Bootstrapper:28 char:28
+ 
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WorkflowReturnException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Workflow.WorkflowReturnException,Microsoft.PowerShell.Commands.Writ 
   eErrorCommand
    + PSComputerName        : [localhost]

Как я могу это исправить ? Есть ли особый способ завершить рабочий процесс?

Вот часть, относящаяся к параллельному выполнению:

foreach -Parallel ($remoteHost in $selectedHosts) {
    if($Env:FULL -eq "true") {
        $process = Start-Process -PassThru -Wait -NoNewWindow "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" "xxx --full"
    } else {
        $process = Start-Process -PassThru -Wait -NoNewWindow "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" "xxx"
    }
    if($process.ExitCode -ne 0) {
        Exit $process.ExitCode
    }
}

Спасибо.

Рабочие процессы отличаются от Windows PowerShell… рабочий процесс может выглядеть как функция с другим ключевым словом, но ... не дайте себя обмануть - самое важное, что нужно знать о рабочих процессах, - это то, что они выглядят как Windows PowerShell, но на самом деле таковыми не являются.

Источник: Рабочие процессы: основы (под Работа и рабочие процессы основная статья на Привет, сценарист! Блог).

Следующий частично прокомментированный сценарий может помочь. Протестировано с использованием очень простых параметров, переданных в MSDeploy.exe такой, что

  • -help -verb действителен, код выхода = 0, а другие
  • -help -brew и -help -bubu нет, код выхода = -1.
  • Также обратите внимание, что -NoNewWindow без -RedirectStandardOutput и -RedirectStandardError вызовет следующую ошибку (рассмотрите возможность пропуска -NoNewWindow параметр вообще):

Microsoft.PowerShell.Utility\Write-Error: Ошибка обработки данных фонового процесса. Сообщается об ошибке: Невозможно обработать элемент с типом узла «Текст». Поддерживаются только типы узлов Element и EndElement.

workflow procWorkflow {

    ## workflow parameter
    param( $selectedHosts )

    ## $using: prefix allows us to call items that are in the workflow scope
    ##         but not in the function / inlinescript scope.
    Function myStartProcess {
        param( [string] $lineargs )
        $process = Start-Process `
            -FilePath "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" `
            -PassThru -Wait -NoNewWindow `
            -RedirectStandardOutput "$env:TEMP\$using:remoteHost`Out.txt" `
            -RedirectStandardError  "$env:TEMP\$using:remoteHost`Err.txt" `
            -ArgumentList $lineargs
        $process.ExitCode                  # function return value
    }
    ## parallel foreach loop on workflow parameter
    foreach -Parallel ($remoteHost in $selectedHosts) {
        if($Env:FULL -eq "true") {
            # omitted as I know that there is no $Env:FULL variable defined on my comp
        } else {
            $processEx = myStartProcess "-help -$remoteHost"
            ###              tried instead above function call:
            ### $lineargs = "-help -$remoteHost"
            ### $process  = Start-Process -FilePath "C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -PassThru -Wait -NoNewWindow -RedirectStandardOutput "$env:TEMP\$remoteHost`Out.txt" -RedirectStandardError "$env:TEMP\$remoteHost`Err.txt" -ArgumentList $lineargs
            ###     and then tried following output alternatives:
            ### $processEx = $process.ExitCode            # null  !!!
            ### $processEx = $process.HasExited           # false !!!
            ### $processEx = $process.GetType().FullName  # System.Management.Automation.PSObject
            ### $processEx = $process                     # System.Diagnostics.Process (msdeploy)
        }
        Write-Output  @{ $remoteHost = $processEx }  # workflow return value
    }
}

Вышеуказанный рабочий процесс возвращает массив хэш-таблиц (примерно hostname: exitcode пары), потому что простого кода выхода будет недостаточно, так как порядок вывода случайный, поскольку он выполнялся параллельно.

## example call to above workflow would look like
$procWorkflow = procWorkflow 'verb','brev','bubu'

## example output processing
"`n=== procWorkflow raw:"
$procWorkflow

"`n=== procWorkflow processed:`n"
for ($i=0; $i -lt $procWorkflow.Count; $i++) {
    $procWorkflow[$i].Keys | ForEach-Object {
        $procExitcode = $procWorkflow[$i][$_]
        if ( $procExitcode -eq 0 ) {
            $procOutFile = Get-Item "$env:TEMP\$_`Out.txt"
        } else {
            $procOutFile = Get-Item "$env:TEMP\$_`Err.txt"
        }
        '{0,-6} {1,6} {2,12}    {3}' -f 
            $_, $procExitcode, $procOutFile.Length, $procOutFile.Name
    }
}

Вывод:

PS D:\PShell> D:\PShell\SF\805314_workflow.ps1

=== procWorkflow raw:

Name                           Value                                                 
----                           -----                                                 
bubu                           -1                                                    
brev                           -1                                                    
verb                           0                                                     

=== procWorkflow processed:

bubu       -1           56    bubuErr.txt
brev       -1           56    brevErr.txt
verb        0          537    verbOut.txt