Page History
Table of Contents |
---|
Introduction
- PowerShell® is a frequently used scripting language available for Linux, MacOS, Windows and other platforms.
- JS7 offers the JS7 - PowerShell Module for simplified access to the JS7 - REST Web Service API
- This article explains some common ways how to handle of handling run-time errors in PowerShell® job scripts.
Scenario
- The examples below examples use a common scenario to raise a run-time error:
- a workflow is assigned a variable
lookup_path
variable that specifies a directory that which is tested in a later job to exist see whether or not to existit exists. - the PowerShelll cmdlet PowerShell®
Test-Path
cmdlet is used to test for the existence of the directory. The implication functioning of the cmdlet is that:- it returns
$True
if the directory exists and$False
if it does not exist, - it raises an exception if the cmdlet parameter for the directory includes a
$Null
value.
- it returns
- a workflow is assigned a variable
- In a perfect world script developers would check if a variable holds a null value before even using it. However, this world is far from being perfect. In addition, the script code required to perfectly check variables for null values would exceed by far the amount of code required for the effective processing of business logic. As a result, hardly anybody implements such checks.
- The examples below examples can be executed by adding an order, for example from the JOC Cockpit Workflows view in two variants:
- add the order without modification of the
lookup_path
variable: the example will run without error, - add the order and modify the value of the
lookup_path
variable to an empty string: an error will be raised:
x
- add the order without modification of the
PowerShell Profiles
PowerShell® profiles can be used to modify defaults available with PowerShell®.
- A PowerShell® profile will be used if available from one of the locations offered provided by the respective platform (Windows, Linux, MacOS etc., please check applicability of profiles for your platform).
- You can examine the global
$PROFILE
variable to verify applicable profile locations:PS C:\> $PROFILE | Get-Member
Profile locations typically are applied from the following properties in descending order. This includes means that all profiles from any all locations are applied if available.
$PROFILE.AllUsersAllHosts
$PROFILE.AllUsersCurrentHost
$PROFILE.CurrentUserAllHosts
$PROFILE.CurrentUserCurrentHost
- By default JS7 by default does not make use of a specific PowerShell® profile, instead the above order of available profiles applies.
...
This situation boils down to defaults available with PowerShell®.
- Built-in defaults of PowerShell® apply.
- Defaults that are modified by a PowerShell® profile.
Continue Processing in case of Errors
The global $ErrorActionPreference
variable makes use of the default value continue
. As a result:
- the job script reports error messages to the stderr channel,
- the job script continues to run after being hit by an error.
This is the most undesirable scenario as it implies that the PowerShell® script:
- continues and might perform very bad things, for example if a cmdlet such as
Remove-Item -Path /$env:LOOKUP_PATH -Recurse
would be used with$env:LOOKUP_PATH
evaluating to null. - completes with an exit code 0 signaling success if the last cmdlet executed with the script was successful. JS7 cannot know that an error occurred and users will not be notified.
Find Download the below example for downloadexample below (.json upload): pdErrorPowerShell_01_No_Handling_Continue.json
...
The global $ErrorActionPreference
variable in this example is set to the value stop
. As a result:
- the job script reports error messages to the stderr channel,
- the job script stops immediately stops after being hit by an error.
This is a somewhat acceptable scenario as it prevents the PowerShell® script to continue from continuing and it raises an exception that is considered recognized by JS7 that and which will fail the job.
Find Download the below example for downloadexample below (.json upload): pdErrorPowerShell_01_No_Handling_Stop.json
...
Code Block | ||||
---|---|---|---|---|
| ||||
#!/usr/bin/env pwsh # global setting: stop execution in case of errors $ErrorActionPreference = "stop" $lookupPath = $env:LOOKUP_PATH if ( !$lookupPath ) { $lookupPath = $null } If ( Test-Path -Path $lookupPath -PathType container ) { Write-Host "path found: $env:LOOKUP_PATH" } else { Write-Host "path not found: $env:LOOKUP_PATH" } |
...
This situation boils down to defaults available with PowerShell® and to the handling of errors with jobs.
- Built-in defaults of PowerShell® apply.
- Defaults that are modified by a PowerShell® profile.
- Error detection by JS7, returning exit codes and controlling exceptions.
...
The global $ErrorActionPreference
variable can have any value. For reasons explained above it is recommended to set that the variable is set to the value stop
.
In addition, JS7 error detection is activated: any output to the stderr channel is considered to signal that the job being has failed. This is achieved by use of using the respective relevant setting in the "Job Options" tab of the property editor in the JOC Cockpit Workflows view:
As a result:
the job script can report errors by use of using the
Write-Error
cmdlet,- the global
$ErrorActionPreference
variable determines if processing is to be stopped or is continued, - errors are reported and notified by JS7.
Find Download the below example for downloadexample below (.json upload): pdErrorPowerShell_02_WriteError.json
...
Code Block | ||||
---|---|---|---|---|
| ||||
#!/usr/bin/env pwsh # use of Write-Error cmdlet # consider the job options to fail if output to stderr is detected $lookupPath = $env:LOOKUP_PATH if ( !$lookupPath ) { Write-Error "empty lookup path not accepted" } if ( Test-Path -Path $lookupPath -PathType container -ErrorAction stop ) { Write-Host "path found: $env:LOOKUP_PATH" } else { Write-Host "path not found: $env:LOOKUP_PATH" } |
...
Setting a non-zero exit code in a PowerShell® script performs two operations:
- it stops processing of the script,
- it forwards the exit code to JS7.
This works independently from of:
- setting the global
$ErrorActionPreference
variable to a specific value and
...
- error detection from the stderr channel by JS7.
Find Download the below example for downloadexample below (.json upload): pdErrorPowerShell_03_Exit.json
...
Code Block | ||||
---|---|---|---|---|
| ||||
#!/usr/bin/env pwsh # use of Write-Error cmdlet # exit script with an exit code $lookupPath = $env:LOOKUP_PATH if ( !$lookupPath ) { Write-Host "empty lookup path not accepted" Exit(12) } if ( Test-Path -Path $lookupPath -PathType container -ErrorAction stop ) { Write-Host "path found: $env:LOOKUP_PATH" } else { Write-Host "path not found: $env:LOOKUP_PATH" } |
Control Exceptions with Try/Catch
Use of the PowerShell PowerShell® Try/Catch
instructions offers full control of error handling in case of errors:
- it stops processing of commands in the
Try
block, - it allows to handle handling of errors in the
Catch
block that should not prevent further execution of the script, - it allows to handle handling of errors in the
Catch
block that which prevent further execution of the script, e.g. by use of theWrite-Error
cmdlet that raises an exception that which is forwarded to JS7.
This works independently from of:
- setting the
$ErrorActionPreference
variable to a specific value and
...
- error detection from the stderr channel by JS7.
Find Download the below example for downloadexample below (.json upload): pdErrorPowerShell_04_Try_Catch.json
...
Code Block | ||||
---|---|---|---|---|
| ||||
#!/usr/bin/env pwsh $lookupPath = $env:LOOKUP_PATH if ( !$lookupPath ) { $lookupPath = $null } try { If ( Test-Path -Path $lookupPath -PathType container ) { Write-Host "path found: $env:LOOKUP_PATH" } else { Write-Host "path not found: $env:LOOKUP_PATH" } } catch { $message = $_.Exception | Format-List -Force | Out-String Write-Error "error occurred: $message" } |
...