How to stop a PowerShell script on the first error?
I want my PowerShell script to stop when any of the commands I run fail (like set -e
in bash). I'm using both Powershell commands (New-Object System.Net.WebClient
) and programs (.\setup.exe
).
Solution 1:
$ErrorActionPreference = "Stop"
will get you part of the way there (i.e. this works great for cmdlets).
However for EXEs you're going to need to check $LastExitCode
yourself after every exe invocation and determine whether that failed or not. Unfortunately I don't think PowerShell can help here because on Windows, EXEs aren't terribly consistent on what constitutes a "success" or "failure" exit code. Most follow the UNIX standard of 0 indicating success but not all do. Check out the CheckLastExitCode function in this blog post. You might find it useful.
Solution 2:
You should be able to accomplish this by using the statement $ErrorActionPreference = "Stop"
at the beginning of your scripts.
The default setting of $ErrorActionPreference
is Continue
, which is why you are seeing your scripts keep going after errors occur.
Solution 3:
Sadly, due to buggy cmdlets like New-RegKey and Clear-Disk, none of these answers are enough. I've currently settled on the following code in a file called ps_support.ps1
:
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
function ThrowOnNativeFailure {
if (-not $?)
{
throw 'Native Failure'
}
}
Then in any powershell file, after the CmdletBinding
and Param
for the file (if present), I have the following:
$ErrorActionPreference = "Stop"
. "$PSScriptRoot\ps_support.ps1"
The duplicated ErrorActionPreference = "Stop"
line is intentional. If I've goofed and somehow gotten the path to ps_support.ps1
wrong, that needs to not silently fail!
I keep ps_support.ps1
in a common location for my repo/workspace, so the path to it for the dot-sourcing may change depending on where the current .ps1
file is.
Any native call gets this treatment:
native_call.exe
ThrowOnNativeFailure
Having that file to dot-source has helped me maintain my sanity while writing powershell scripts. :-)