1

I have ./main.ps1 that calls ./worker1.ps1 and worker2.ps1 with parameters, lines from main.ps1:

# other stuff in main script
$args = @()
$args += ("-PARAM1", "$VAR1")
$args += ("-PARAM2", "$VAR2")
$worker1 = "./workers/worker1.ps1"
Invoke-Expression "$worker1 $args" -ErrorAction Stop
# other stuff in main script
$worker2 = "./workers/worker2.ps1"
Invoke-Expression "$worker2 $args" -ErrorAction Stop

If worker1.ps1 fails it has exit 1 line,
The problem is that even when worker1.ps1 fails worker2.ps1 is called by main.ps1

How could I avoid that and fail main script as soon as one of the called fails?

kagarlickij
  • 7,327
  • 10
  • 36
  • 71
  • 2
    For one thing, **don't use** the self-defined variable name `$args`, because this is an [Automatic variable](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7#args) – Theo Jun 13 '20 at 19:58
  • 1
    Does this answer your question? [How to get status of "Invoke-Expression", successful or failed?](https://stackoverflow.com/questions/32348794/how-to-get-status-of-invoke-expression-successful-or-failed) – Theo Jun 13 '20 at 20:01

4 Answers4

3

To put it all together:

# other stuff in main script

# Define the arguments as a *hashtable*.
$htArgs = @{
  PARAM1 = $VAR1
  PARAM2 = $VAR2
}

foreach ($worker in './workers/worker1.ps1', './workers/worker2.ps1') {
  & $worker @htArgs # Note the @ sigil for splatting
  if ($LASTEXITCODE) { Throw "$worker signaled failure via exit code $LASTEXITCODE" } 
}
mklement0
  • 382,024
  • 64
  • 607
  • 775
2

Since I didn't have your programs to work on I created a couple to duplicate what I thought you were saying, e.g. the Worker1.ps1 returned a 1 when it failed.

So the main program looks like this:

$TFArgs = @{ReturnCD = 0
            CallNumber = 1}


$RVal = & .\test\Test-CallFail.ps1 @TFArgs 
$RVal
Write-Host " "

If ($RVal -ne 1) {
       $TFArgs = @{ReturnCD = 1
                   CallNumber = 2}
  $RVal = & .\test\Test-CallFail.ps1 @TFArgs
  $Rval
}  

The called program looks like this:

Param (
  [INt] $ReturnCd,
  [Int] $CallNumber
)

Write-Host "Call Number: $CallNumber"
"$ReturnCd"

So if the first call has a ReturnCD of 0. i.e. success the output will look like this:

Call Number: 1
0

Call Number: 2
1

If you change the ReturnCD to 1, i.e. failed it looks like this:

Call Number: 1
1

The second call was not made.

HTH

RetiredGeek
  • 2,980
  • 1
  • 7
  • 21
1

$Result = Invoke-Expression "$worker1 $args" -ErrorAction Stop

other stuff in main script

if ($Result) { $worker2 = "./workers/worker2.ps1" Invoke-Expression "$worker2 $args" -ErrorAction Stop }

Mike
  • 33
  • 4
  • The OP has indicated that the scripts signal failure via `exit 1`, not via their _output_. On a general note: please [format your code and sample input/output properly](http://meta.stackexchange.com/a/22189/248777). – mklement0 Jun 13 '20 at 21:18
0

After a few attempts I've found simple way:

# other stuff in main script
& ./workers/worker1.ps1 -PARAM1 "$VAR1" -PARAM2 "$VAR2"
if ($LASTEXITCODE -ne 0) {
    Write-Output "worker1 has failed"
    exit 1
} else {
    Write-Output "worker1 has completed"
}
# other stuff in main script
& ./workers/worker2.ps1
kagarlickij
  • 7,327
  • 10
  • 36
  • 71