Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell try/catch/finally

I recently wrote a PowerShell script that works great - however, I'd like to now upgrade the script and add some error checking / handling - but I've been stumped at the first hurdle it seems. Why won't the following code work?

try {   Remove-Item "C:\somenonexistentfolder\file.txt" -ErrorAction Stop }  catch [System.Management.Automation.ItemNotFoundException] {   "item not found" }  catch {   "any other undefined errors"   $error[0] }  finally {   "Finished" } 

The error is caught in the second catch block - you can see the output from $error[0]. Obviously I would like to catch it in the first block. What am I missing?

like image 686
steve Avatar asked Jul 21 '11 16:07

steve


People also ask

How do you use try catch finally in PowerShell?

A try statement can include multiple catch blocks for the different specified error types. The finally keyword is followed by a statement list that runs every time the script is run, even if the try statement ran without error or an error was caught in a catch statement. Note that pressing CTRL + C stops the pipeline.

How do I catch a PowerShell error?

Try/Catch/Finally The Try, Catch, and Finally blocks in PowerShell allow us to capture terminating errors. The Try block contains the code you'd like to execute, and catch any potential errors that happen. The Catch block contains the code you'd like to execute after a terminating error has occurred.

Can I use try catch finally?

catch statement is comprised of a try block and either a catch block, a finally block, or both. The code in the try block is executed first, and if it throws an exception, the code in the catch block will be executed. The code in the finally block will always be executed before control flow exits the entire construct.

Does try catch stop execution PowerShell?

“try” is a PowerShell block that you want PowerShell to monitor for errors. When any error occurs during the script execution, it will immediately stop at that point and move onto the Catch block if the error is a terminating error.


2 Answers

-ErrorAction Stop is changing things for you. Try adding this and see what you get:

Catch [System.Management.Automation.ActionPreferenceStopException] { "caught a StopExecution Exception"  $error[0] } 
like image 197
Bruce Avatar answered Oct 13 '22 11:10

Bruce


That is very odd.

I went through ItemNotFoundException's base classes and tested the following multiple catches to see what would catch it:

try {   remove-item C:\nonexistent\file.txt -erroraction stop } catch [System.Management.Automation.ItemNotFoundException] {   write-host 'ItemNotFound' } catch [System.Management.Automation.SessionStateException] {   write-host 'SessionState' } catch [System.Management.Automation.RuntimeException] {   write-host 'RuntimeException' } catch [System.SystemException] {   write-host 'SystemException' } catch [System.Exception] {   write-host 'Exception' } catch {   write-host 'well, darn' } 

As it turns out, the output was 'RuntimeException'. I also tried it with a different exception CommandNotFoundException:

try {   do-nonexistent-command } catch [System.Management.Automation.CommandNotFoundException] {   write-host 'CommandNotFoundException' } catch {   write-host 'well, darn' } 

That output 'CommandNotFoundException' correctly.

I vaguely remember reading elsewhere (though I couldn't find it again) of problems with this. In such cases where exception filtering didn't work correctly, they would catch the closest Type they could and then use a switch. The following just catches Exception instead of RuntimeException, but is the switch equivalent of my first example that checks all base types of ItemNotFoundException:

try {   Remove-Item C:\nonexistent\file.txt -ErrorAction Stop } catch [System.Exception] {   switch($_.Exception.GetType().FullName) {     'System.Management.Automation.ItemNotFoundException' {       write-host 'ItemNotFound'     }     'System.Management.Automation.SessionStateException' {       write-host 'SessionState'     }     'System.Management.Automation.RuntimeException' {       write-host 'RuntimeException'     }     'System.SystemException' {       write-host 'SystemException'     }     'System.Exception' {       write-host 'Exception'     }     default {'well, darn'}   } } 

This writes 'ItemNotFound', as it should.

like image 27
Joel B Fant Avatar answered Oct 13 '22 12:10

Joel B Fant