- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
The try/catch block with an optional finally block creates a "box" around code that forces it to send all thrown exceptions into the catch block for further processing.
PowerShell has two types of errors: terminating errors and non-terminating errors. When you see that nasty red text on the screen, you can immediately see an error has occurred, but you can't immediately figure out if that error was a terminating or non-terminating error. All you see is red text!
Was there code skipped underneath the spot where the error occurred? If so, it was probably a terminating error. If PowerShell displayed an error but kept processing the rest of the script, chances are it was a non-terminating error. Non-terminating errors do not change code execution. They simply send data out to the error stream and keep going. Terminating errors, on the other hand, terminate the script unless enclosed in a try block.
To simplify things, let's just make all errors terminating by setting $ErrorActionPreference to Stop. This tells PowerShell to treat all errors as terminating even if they start out as non-terminating. A terminating error is the only way we can catch an exception with our catch block.
I'll create a function and then force PowerShell to return an error. Notice I have a Write-Host reference after the error that should also return "I am the code after the error."
function Do-Something { param() $ErrorActionPreference = 'Stop' ## Do stuff here ## Return an error Write-Error -Message 'Oh no! An error!' Write-Host 'I am the code after the error' }
I execute this function to produce the result below:
Notice this never returned "I am the code after the error." This is because Write-Error "threw" an exception or a hard-terminating error that stopped execution altogether. Also, notice we did get the typical red text we're used to.
Perhaps instead of just returning an error to the console, we'd like to do something with this error or perform some other kind of action when it returns an error. This is called error handling. We need a way to capture that exception before it gets to the console. To do that, we can wrap the code inside of a try block accompanied by a catch block.
I don't like that red text, so I'd rather just see the error message and format it in green text. I can make that happen by adding Write-Host in the catch block and returning just the message as shown below.
function Do-Something { param() $ErrorActionPreference = 'Stop' try { ## Do stuff here ## Return an error Write-Error -Message 'Oh no! An error!' Write-Host 'I am the code after the error' } catch { Write-Host $_.Exception.Message -ForegroundColor Green } }
This Write-Host example is obviously not too realistic, but inside of the catch block you can do anything. You can revert any changes previously made, return the status of a server, or do nothing at all and leave the catch block blank (not recommended).
Our example function will never execute Write-Host 'I am the code after the error' because Write-Error is throwing the exception into the catch block. But what if I really need this to run regardless of whether it throws an exception or not? In that case, I can add a finally block below the catch block.
function Do-Something { param() $ErrorActionPreference = 'Stop' try { ## Do stuff here ## Return an error Write-Error -Message 'Oh no! An error!' } catch { Write-Host $_.Exception.Message -ForegroundColor Green } finally { Write-Host 'I am the code after the error' } }
Notice now it returned the text and will return it whether or not it throws an exception into the catch block. It always executes code inside the finally block regardless of whether it catches an exception or not. The finally block is good for inserting cleanup code like closing down database connections, removing any temporary files created, and so on. PowerShell always executes code inside the finally block.
Subscribe to 4sysops newsletter!
If your code is complex and lots of different commands can throw exceptions, it's always a good idea to enclose the code inside a try block and catch exceptions as they come up. Good error handling shows that the author has not only ensured that the code worked as designed but has also thought ahead and anticipated any problems that may arise as well.
We can also write code without ‘finally’, simply after ‘catch’…
@wand3rvogel,
There is an interesting information in the official documentation (Microsoft Docs).
What is your opinion on following article from Powershell Station?
https://powehttps://powershellstation.com/2017/10/03/missing-point-powershell-error-handling/rshellstation.com/2017/10/03/missing-point-powershell-error-handling/
According to Mike, he suggests it is better to use something like -ErrorAction Silentlycontinue and -ErrorVariable Err in a Try/Catch block..
You’re using the ‘$ErrorActionPreference = Stop’ automatic variable in your example…why not use the ‘$ErrorAction = Stop’ parameter under section ‘#Do Stuff here’ ?
Thanks for sharing
Gyz