
I know what some of you are thinking when reading this BLOG – I do not need error handling, I only use PowerShell for one-line commands, or PowerShell is not a development language… Well, I am here to tell you… You actually do need it, and it is actually super easy to accomplish.
There are a lot of ways to actually build in error handling or checking into your PowerShell code, sometimes in ways that are not even meant to be error handling. I know when I was new to PowerShell, or writing anything for that fact, I used to do a lot of output writing to check my code. Consider the following:
$basetext = "testing"
for($i=0; $i -lt 5; $i++)
{
$basetext = $basetext + $i
}
This is a simplistic piece of code that simply steps through a FOR statement and adds the next value of variable $i to the text string. It has no practical use really, but the traditional ways of error handling will not allow you to know if this is working the way you expected. I simply add the following line inside of the FOR statement to check if it is the proper output.
$basetext = "testing"
for($i=0; $i -lt 5; $i++)
{
$basetext = $basetext + $i
Write-Output $basetext
}
The Write-Output command will simply spit out the value of $basetext each time and allow me to make sure that the value I am expecting is true is accurate. Now, is this true error handling, the correct answer is no, but I wanted to share this since it is not always the procedural error handling that will assist in every situation. If the above code is executed with line 6 reading $basetext + $i then the result would not be what you are expecting, although, technically no errors would be thrown.
So, with that little tidbit of information out of the way, let’s look at traditional error handling with PowerShell. PowerShell has a CMDlet called Write-Error which allows you to do just that – to write an error to the output. However, this will not do exactly what you would expect it to do without some “tweaking”. Consider I write the following lines:
$sum = 2 + 1
if($sum -ne 4)
{
Write-Error "It did not work"
}
Write-Host "The correct answer to 2+2 = $sum"
(And yes, those of you who are possibly a little more advanced will see that if I add an ELSE block here I could handle this differently – But humor me and everyone else, and just go with it 😊) Now, if you look at my sort of ridiculous but effective example – you will expect this block of code to result in a message to the user that it did not work and that would be the end of it. However, this is not true, there WILL be an error message written out to the users letting them know the calculation did not work, unfortunately, there will ALSO be a message written out to the users letting them know that 2+2 = 3 – OH NO!

Why does this happen? Because by itself, the Write-Error CMDlet does not throw a terminating error, it simply is outputting a given input as the error. However, by adding -ErrorAction Stop to this CMDlet we can then force a terminating error that will not only stop the code where we want it to stop but it can also be utilized in a Catch (Which we will get to shortly) so that the error can be dealt with. So, what does that look like? Let’s see

With the -ErrorAction Stop parameter in place, this code now throws a terminating error which can be caught and will also stop the code in its tracks. There are other actions available for the ErrorActon parameter, they are as follows:
- Continue – This is the default action that throws the error but continues to execute – This is why without any specification of this parameter, we were given the first outcome
- Ignore – As stated, this throws zero error and just continues executing the code
- SilentlyContinue – Same as continue, except it throws no visible error, but the error is still recorded
- Suspend – This is only available in a PowerShell workflow – allows for the workflow to be suspended while the error is investigated
- Inquire – This will halt the code, and ask the user for input on how to handle the error

OK great, we have thrown an error, now, what do we do with that error? Do we always want the error to terminate the entire block of code? What if we could remedy the error inside of the code? How do we log what the error was? The good news, all of these are possible. There is a built-in variable in PowerShell $Error which houses all of the errors that have been thrown/generated during the current PowerShell session. I will demonstrate:

As you can see in the example above – I generated an error with Write-Error, and then the $Error variable, which may look to be an array object, but it is actually a custom PS object called System.Management.Automation.ErrorRecord – if I access the newest record of $Error at [0] – I see the exact same error that I had generated. This is helpful to be able to go back and pull earlier generated errors for logging and tracking purposes. So, now what if we want to be able to handle an error in-line with the code without terminating the entire script, but also being able to modify the outcome as well as log the error? This is where we can utilize the Try-Catch block in PowerShell.
Try-Catch will allow us to throw a terminating error, handle it with custom output or logging, and still be able to continue executing the rest of the script properly. Let’s take a look
$rgname = "Test RG"
$machines = Get-Content C:\temp\machines.txt
foreach($item in $machines)
{
Start-AzVm -ResourceGroupName $rgname -Name $item
}
In the above example, we are taking the contents of what we will say is a txt file of Azure Virtual Machine names and we are stepping through those names to start the VMs. Now, if the txt file has some names let’s say that have been deleted or are improperly typed, this is going to cause some issues as the script executes through the array of machines. For each machine that is not named properly in the txt file or is overall just missing or non-existant, it will throw an error to the console that you can view as you run the script (Granted this is not being ran as a PowerShell background job) So technically, you could watch this script as it runs, and you could write down every single machine name as it errors out, and then also copy down the error that is generated so you can investigate all of the machines when it is finished. Does not sound like something I want to be doing while this script runs – why don’t we capture the machine names and the corresponding errors in a variable to deal with later? This sounds a lot more promising. Let’s perform a Try-Catch

In this example above – We have instituted a Try-Catch block to handle the errors properly. Do not worry if you do not understand everything that is happening, especially in the Catch block – but takeaway from this the fact that the error is now being handled properly. Inside of the Try block, you see that we are simply running the same command as in the first example, except we have also added the -ErrorAction Stop parameter. Now, you are probably saying, wait a minute, that is now a terminating error, doesn’t that now break the execution of the code after the first error? No, it does not, and that is the beauty of the Try block, is that it detects that terminating error, and then throws the error and the code execution down to the Catch block to continue to execute it’s block of code. Now, technically, you could leave the Catch block blank, nothing will happen or be output to the console, and the code will just continue. Honestly, if that is your intent, a simple ErrorAction -SilentlyContinue would achieve the same thing – no what we are looking for here is an action to follow up this error. The code inside of the Catch block is simply assigning a variable to the latest captured error (which in this case would be the error that the Try block captured) and creating a custom PS object to record both the machine name and the corresponding error and then adding those two pieces of data to an array that we created in the beginning of the script. This way, when the script is finished, instead of having a console screen full of errors that you would have needed to jot down or do some weird copy and paste from the console, you now will have a neat array containing the machines and errors that you can easily use to investigate.
You can also utilize more than one Catch in a Try Catch block – especially if you want to be able to capture specific errors and perform different actions on this errors. The following example shows handling a specific error in a try catch block

In the above example, we have 2 catch statements, both of which perform different actions, but the first one is looking for a specific error. Multiple catch statements will walk down the statements in order until the error either matches the error it is looking for, or there is a catch-all for the errors. In this case, if there is a specific FileNotFoundException error, this block of code will then output the provided string to the console as an error, and if it is any other type of error, it will simply output the error itself to the console. Specific catch blocks can be useful when you want to handle a specific error in a different way.
These are a couple different ways you can successfully utilize error handling in PowerShell. Just remember, that no matter how small your block of code is, it can always benefit from error handling. Small blocks of code become big blocks in no time, and you will wish you were handling those errors properly from the beginning.
Happy PowerShelling!































