Exchange PowerShell Quickstart – Part 5

Over the past four parts we have covered connecting to Exchange and discovering cmdlets in part 1. We explored the pipeline in part 2 followed by hash tables, arrays and variables in part 3, and flow control in terms of conditional and iterative processing in part 4. This week we are going to cover different error handling techniques

When writing powershell there are four main ways of handling errors. One is to just deal with the ugly red text in the PowerShell window when they happen. This is the easiest to program of course, but not the most elegant.
The second option is to use ErrorAction, the third option is to use try catch blocks and the last option is to use trap statements

ErrorAction

The ErrorAction common parameter is available with pretty much every PowerShell cmdlet. In fact if you look at get-help about_CommonParameters you’ll see a lot more of these standard parameters listed, which are good to remember and get to grips with. ErrorAction can have one of four values

SilentlyContinue

SilentlyContinue is the one most often used to suppress an error that you think may happen. The command will not print out any error message, however the error itself is added to a built-in array variable called $error. This special variable can be emptied by using $error.clear(), and the new error is always in position 0.

Continue

Continue is the default, it will print the error and then continue running the pipeline

Inquire

Inquire will also print the error and then ask the user if they wish to continue (I must admit I’ve never used this option)

Stop

Stop will again print out the error and then stops running the command or pipeline altogether

Now I do use ErrorAction quite a lot, especially when doing something like Get-Mailbox if I don’t know if the mailbox I am looking for is there or not, so for example

$Mailbox = Get-Mailbox a.user@somewhere.com -ErrorAction SilentlyContinue
if( $Mailbox ) {
   # Alright we have a mailbox, let's carry on
} else {
   write-host 'No Mailbox found'
}

Try Catch

When you are writing more complicated scripts and want to capture any and all errors that is when the try catch method really comes to the fore. Using Try Catch is pretty simple but once you start nesting different levels it can become more complex. I like to try to avoid the nesting for that reason whereever possible…

try{
   [int]$i = 'One'
} catch {
   write-host $error[0]
}

Now the above catch statement will literally catch any error at all, you can see that it is still writing to the $error variable, so we can interrogate what happened. If we want to have different catches for different kinds of error then we can change the above slightly. First we need to find out what the actual error type is. The simplest way is to force the error without a catch statement

[int]$i = 'One'

Cannot convert value "One" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:5
+ [int]$i = 'One'
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException

And then take the MetadataError which is ArgumentTransformationMetadataException and ask Google. In the first result which is the MSDN page for the ArgumentTransformationMetadataException Class, we see that the namespace is System.Management.Automation. This means that we can do the following

try{
   [int]$i = 'One'
} catch [System.Management.Automation.ArgumentTransformationMetadataException] {
   write-host $error[0] -foregroundColor Green
} catch {
   write-host $error[0]
}

And now the error will be printed in Green, but any other types of errors would use the normal catch. Of course the above are just trivial examples but they are just to illustrate the mechanism.

One extension to this is the finally block. This allows you to have some cleanup code that will always run even if there was an error

try{
   [int]$i = 'One'
} catch [System.Management.Automation.ArgumentTransformationMetadataException] {
   write-host $error[0] -foregroundColor Green
} catch {
   write-host $error[0]
} finally {
   $i = 'One'
   write-host $i
}

Now it shows the error in green as before, but then runs the finally block and writes the value One

Trap

There is another way of trapping errors, but personally I’ve never used it in any PowerShell scripts. This is to use the trap statement, for example the above try catch could be re-written as follows

Function test {
   trap [System.InvalidCastException] { write-host $error[0] -foregroundColor Green }
   trap { write-host $error[0] }
   [int]$i = 'One'
}

test

Notice that a trap can’t just be used on the command line, it has to be within a script or a function, and also notice that simply by putting the same code into a function the actually trap type changes altogether.

I personally find that I use the ErrorAction SilentlyContinue to trap any expected errors, and use try catch for the unexpected ones so that users get a friendlier message

There is a lot more that can be said about PowerShell, but I hope this has given you a quickstart into writing basic PowerShell scripts. If there is a demand that I will write about more advanced topics such as the select, sort, group, measure cmdlets and the different format-* cmdlets.

Until next time, happy shelling!

Twan van Beers

Twan is a senior consultant with over 20 years of experience. He has a wide range of skills including Messaging, Active Directory, SQL, Networking and Firewalls. Twan loves to write scripts and get deep and dirty into debugging code, in order to understand and resolve the most complex of problems.

Leave a Reply

Your email address will not be published. Required fields are marked *

Search