Powershell Simplified Part 7: Error Handling

Exception handling in Powershell is primarily based on try-catch-finally and trap. Let’s see some scenarios,

function throws-error { throw "an error occured here" }
throws-error        # unhandled exception - script will error out

If we want to catch an error, we can use the try-catch construct,

function throws-error {
    # we can throw a .NET exception too
    throw [System.IO.FileNotFoundException] "throwing a filenotfoundexception"
}

try { throws-error }
catch {
    # let's get some more information about the error
    write-host $_
    $_.GetType().FullName              # the type of $_ is 'System.Management.Automation.ErrorRecord'
    $_.Exception
    $_.Exception.GetType().FullName    # the exception type name is 'System.IO.FileNotFoundException'
    $_.Exception.Message               # the exception message 
}

Just like in C#, we can catch different types of exceptions with a single try. Order is important, catch the most specific exceptions first.

function throw-errors([int]$errorType) {
    switch ($errorType) {
        1 { throw [System.IO.FileNotFoundException] "throwing a filenotfoundexception" }
        2 { throw [System.IO.IOException]  "throwing a ioexception" }
        3 { throw [System.SystemException]  "throwing a systemexception" }
        default { throw [System.Exception] "a default error" }
    }
}

try { throw-errors 2 }
catch [System.IO.FileNotFoundException] { "caught filenotfoundexception" }    # catch the most specific exception first
catch [System.IO.IOException] { "caught ioexception" }
catch [System.SystemException] { "caught systemexception" } 
catch [System.Exception] { "caught exception" }                               # catch the most generic exception last
finally { "done" }

Every pre-defined Powershell cmdlet comes with built-in error handling via a common parameter called –ErrorAction. To see this is action try the commands below,

get-process –fileversion                                # you'll get a few errors in the output
get-process -fileversion -erroraction silentlycontinue  # ignore the errors
get-process -fileversion -ea 0                          # 'ea' is the alias for erroraction
get-process -fileversion -errorvariable errors          # get an array of errors that occured
write-host $errors.count                                # how many errors occured?
foreach ($error in $errors) { write-host "Error:" $error }

If you want to import the common parameters into your function then use the CmdletBinding.

function throws-error {
    [CmdletBinding()]              # our function now supports the ErrorAction param implicitly
    param()

    throw "an error occured here"
}

function throws-error2 {
    # ErrorAction actually sets the $ErrorActionPreference, and we can do this ourselves
    $ErrorActionPreference = "silentlycontinue" 

    throw "an error occured here"
}

throws-error -ea 0    # no error is thrown
throws-error2         # no error is thrown

Now let’s look at the other Powershell way of handling exceptions – trap. Traps handle the exception and allow script execution to continue.

trap [IO.FileNotFoundException] { "trapped outside " + $_.Exception; continue; }

function test-trap {
    # break results in re-throwing the exception, so it can be handled by the outer trap
    trap [IO.FileNotFoundException] { "trapped inside " + $_.Exception; break; }

    throw [IO.FileNotFoundException] "a filenotfoundexception"
    "will not output this line"
}

test-trap

The ‘will not output this line’ doesn’t get output because with ‘continue’, execution is returned to the scope the trap is in and the next command is executed. To see this more clearly,

function test-trap {
   trap { "outer " + $_.Exception; continue; }

   if($true) {
        trap { "inner " + $_.Exception; break; }

        throw "an error occured";
        "will not output this line"
   }

   "will output this line"
}

test-trap

We can also trap multiple exceptions, like catch blocks,

function test-trap {   
    throw [IO.FileNotFoundException] "a filenotfoundexception"
    throw (new-object IO.IOException("an ioexception"))        # this is executed because of the 'continue' in the filenotfoundexception trap
    throw (new-object SystemException("a systemexception"))    # note the different way throwing
    throw [Exception] "a default error"

    # order of traps not important
    trap [SystemException]           { $_.Exception; continue; }        # 'continue' execute the next command in the scope of the 'trap'
    trap [IO.FileNotFoundException]  { $_.Exception; continue; }        # 'continue' causes the throw ioexception statement to execute
    trap [Exception]                 { $_.Exception; continue; }
    trap [IO.IOException]            { $_.Exception; continue; }
    
    "done"
}

test-trap

As you can see, using traps are a little tricky, using try-catch should cover most (if not all) your cases.

Advertisements

About soumya chattopadhyay
I live and work in Seattle, WA. I work with Microsoft technologies, and I'm especially interested in C#.

6 Responses to Powershell Simplified Part 7: Error Handling

  1. Pingback: Powershell Simplified Series « I.Net

  2. Pingback: How To Fix Error Object Powershell Errors - Windows Vista, Windows 7 & 8

  3. Pingback: Fix Wpf Command Error Handling Windows XP, Vista, 7, 8 [Solved]

  4. Pingback: Fix C# Powershell Errorrecord Windows XP, Vista, 7, 8 [Solved]

  5. Pingback: Fix Catching Errors Powershell Windows XP, Vista, 7, 8 [Solved]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: