2

I have a PowerShell script that is running many msdeploy concurrently on multiple remote servers using Powershell Workflow.

Everything works fine except that at the end of each "Foreach -Parallel" loop, I get this exception:

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]

How can I fix this ? Is there a specific way to end a workflow ?

Here is the part related to the parallel execution :

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
    }
}

Thank you.

1 Answer 1

2

Workflows differ from the Windows PowerShell … a workflow may look like a function with a different keyword but … don’t be fooled — the most important point to understand about workflows is that they look like Windows PowerShell but they aren’t.

Source: Workflows: The Basics (under Jobs and Workflows main article at Hey, Scripting Guy! Blog).

The following partially commented script could help. Tested using very simple parameters passed to MSDeploy.exe such that

  • -help -verb is valid, exit code = 0 while other
  • -help -brew and -help -bubu aren't, exit code = -1.
  • Also note that -NoNewWindow without -RedirectStandardOutput and -RedirectStandardError would raise following error (consider omitting the -NoNewWindow parameter at all):

Microsoft.PowerShell.Utility\Write-Error: There is an error processing data from the background process. Error reported: Cannot process an element with node type "Text". Only Element and EndElement node types are supported..

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
    }
}

Above workflow returns an array of hash-tables (roughly hostname: exitcode pairs) because a bare exit code would not suffice as the output order is random since it was run in parallel.

## 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
    }
}

Output:

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
2
  • Omiting -NoNewWindow worked for me.
    – Jelphy
    Apr 27, 2018 at 10:34
  • 1
    Regarding There is an error processing data from the background process. Error reported: Cannot process an element with node type "Text". Only Element and EndElement node types are supported.. see: stackoverflow.com/questions/33936510/… Mar 7, 2019 at 15:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .