PowerShell errors come in two flavors – terminating and non-terminating errors.
Terminating errors stop the execution of the code if they are not handled, whereas non-terminating errors do not terminate the current code execution. Instead, the error is raised, and the execution of the rest of the script is continued.
Examples of Terminating and Non-Terminating Errors
Examples of non-terminating errors:
1 2 3 4 |
# Try to get child items of a folder that doesn't exist Get-ChildItem -Path ./test_folder/; Write-Host "Hello World!" # A typo on the cmdlet Get-ChildItme -Path ./test_folder/; Write-Host "Hello World!" |
The above examples show that the errors from Get-ChildItem and Get-ChildItme did not stop the execution of the next command (Write-Host). In the first example, the -Path provided does not exist, and in the second command, we have a typo on the cmdlet (Get-ChildItme instead of Get-ChildItem).
Example of a terminating error – a syntax error:
"56"++67; Write-Host "Hello World!"
Syntax errors like the one shown above are terminating. The execution was halted when ParserError was raised. That was why the Write-Host command was not executed this time round.
The rest of the article discusses ways to stop the execution of a PowerShell script even when a non-terminating error is encountered.
We will be discussing three methods to do that.
Method 1: Using the “Throw” and “Write-Error” Keywords to Raise Exceptions
This method allows the user to raise an error explicitly whenever a given condition is met.
Consider the following PowerShell script. The script checks if a folder exists or not using an if-statement. This code will not raise any error whether or not the folder exists.
File: .\test_script2.ps1
1 2 3 4 5 6 7 8 9 |
$folder = "./test_folder2" # Check if the $folder path exists. if (Test-Path -Path $folder){ Write-Host "Folder exists." } else { Write-Host "Folder doesn't exist!" } # Write into the console. Write-Host "Hello world, this is the end!" |
We can raise a non-terminating error if the folder does not exist using the Write-Error cmdlet, as shown below.
File: .\test_script3.ps1
1 2 3 4 5 6 7 8 9 10 |
$folder = "./test_folder2" # Check if the $folder path exists. if (Test-Path -Path $folder){ Write-Host "Folder exists." } else { # Raising non-terminating error if the folder does not exist Write-Error "Folder doesn't exist!" } # Write into the console. Write-Host "Hello world, this is the end!" |
This time around, a “Folder doesn’t exist!” error is raised, but it’s non-terminating – the code execution is not halted because of this error which is why the Write-Host command in the last line of the script is executed.
To stop the execution of the script if the folder does not exist, you should explicitly raise a terminating error using the “Throw” keyword, as shown below.
File: .\test_script4.ps1
1 2 3 4 5 6 7 8 9 10 11 |
$folder = "./test_folder2" # Check if the $folder path exists. if (Test-Path -Path $folder){ Write-Host "Folder exists." } else { Throw "Folder doesn't exist!" } # Get child items - files and folders within $folder Get-ChildItem -Path $folder # Write into the console. Write-Host "Hello world, this is the end!" |
As shown in the example, “Folder doesn’t exist” raises a terminating exception – when the error is encountered, the execution is stopped.
This approach is useful if the rest of the code depends on whether the folder exists. For instance, in the example above Get-ChildItem command depends on the existence of the $folder being checked in the if-statement.
Method 2: Using Error Related Preference Variables – $ErrorActionPreference and $ErrorAction
There are several error preference variables in PowerShell. This method will cover two of them:
- $ErrorAction
This variable determines how a cmdlet being executed responds to a non-terminating error. Accepted values include: Continue (default), Break, Suspend, Ignore, Inquire, Stop, and, SilentlyContinue.
If we want to stop a PowerShell script on error, we pass the “Stop” value to the variable. Note that this variable only controls the behavior of the cmdlet for which the variable is passed.
- $ErrorActionPreference
This is a global error-related preference variable that determines the behavior of a cmdlet when a non-terminating error is encountered. Like $ErrorAction, the accepted values include Continue (default), SilentlyContinue, Stop, Inquire, Ignore, Suspend, and Break.
If we want to halt PowerShell execution on error, we must pass the “Stop” value to the variable. Unlike the $ErrorAction, $ErrorActionPreference is a global variable; when defined, all non-terminating errors raised after it for the current PowerShell session are affected. It is often defined at the start of the script.
The following code shows how to use the $ErrorAction variable. The comments on the code explain what’s happening in each line.
File: .\test_script5.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$folder = "./test_folder2" # Check if the $folder path exists. if (Test-Path -Path $folder){ Write-Host "Folder exists." } else { # Non-terminating error is raised by the Write-Error command. # $ErrorAction is not passed; therefore, execution will continue Write-Error "Folder doesn't exist!" Write-Host "Hello world 1!" } # Get-Child is not a valid cmdlet - a non-terminating error is raised # $ErrorAction is not passed; therefore, execution will continue Get-Child -Path $folder Write-Host "Hello world 2!" # Get child items - files and folders within $folder # $folder does not exist - non-terminating error is raised and the # Execution because $ErrorAction is set to "Stop" Get-ChildItem -Path $folder -ErrorAction Stop # This command won't be reached Write-Host "Hello world 3!" |
Output:
The last Write-Host command was not executed because the -ErrorAction was set to “Stop” for the Get-ChildItem command in the previous code line (setting $ErrorAction to “Stop” effectively converted the non-terminating error into a terminating one).
Using the $ErrorActionPreference global variable is simple. Just add
$ErrorActionPreference “Stop”
at the top of the script, and the script execution will be stopped as soon as a terminating or non-terminating error is encountered.
Note 1: $ErrorAction overrides the effects of $ErrorActionPreference.
Methods 1 and 2 discussed above primarily work with cmdlets but not with errors from executables. Let’s discuss stopping a PowerShell script on error when working with executables.
Method 3: Checking the Execution Status or the Exit Code
Some standard Windows variables capture the execution status and exit code of a given command or executable. We will discuss two in this case.
- $? – this variable shows the execution status of the last operation. True means the operation was completed successfully with no errors and False means at least one error was encountered.
- $LASTEXITCODE – this variable returns the exit code for the last operation – 0 means success, and one means failure.
- Bonus: $Error variable holds the upto 256 errors generated during the current PowerShell session.
Based on the value returned by $? and $LASTEXITCODE, you can use the if-statement and “Throw” keywords to exit the scrip execution if an error is raised (See Method 1).
Note 2: It is a convention that the $LASTEXITCODE=1 when the last operation was completed successfully and 0 otherwise. Some Windows applications do not obey this convention. It is therefore recommended to check the meaning of the returned exit code on the documentation of the executable you are running.
Conclusion
This article covers three ways of stopping a PowerShell script execution when a non-terminating error occurs.
The first method discussed using the Write-Error cmdlet or Throw keyword to raise non-terminating or terminating explicitly whenever a given condition is met.
In Method 2, we discussed using $ErrorActionPreference and $ErrorAction variables to deal with non-terminating errors. Lastly, we covered how to deal with non-terminating errors when executables.