So I saw this piece of code with try catch. Although the piece of code worked, I didn't agree with the approach.
Let's see what the approaches are and what's the best way. Comments are highly appreciated.
So the actuall piece of code was something like this
# function bla function bla(){ try{ # this will fail, it's not a real command blaaaa }catch{ $ErrorMessage = "Failed to blaaaa. Error : " + $_.Exception.Message throw $ErrorMessage } } # wrapper function blabla function blabla(){ try{ bla bla }catch{ $ErrorMessage = "Failed to blabla. Error : " + $_.Exception.Message throw $ErrorMessage } } # main code try{ blabla }catch{ $ErrorMessage = "Failed. Error : " + $_.Exception.Message throw $ErrorMessage }
What's wrong with this ?
Well, although the error is caught, the original error is harder to trace. Which makes it harder to debug.
Failed. Error : Failed to blabla. Error : Failed to blaaaa. Error : The term 'blaaaa' is no t recognized as the name of a cmdlet, function, script file, or operable program. Check the sp elling of the name, or if a path was included, verify that the path is correct and try again. At line:30 char:5 + throw $ErrorMessage + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (Failed. Error ... and try again.:String) [] , RuntimeException + FullyQualifiedErrorId : Failed. Error : Failed to blabla. Error : Failed to blaaaa. Error : The term 'blaaaa' is not recognized as the name of a cmdlet, function, script fil e, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
This how I like to do it.
- Catch
- Write what's wrong and where it went wrong (using the $MyInvocation.MyCommand you can list the function name - optional but handy
- Re-throw the original exception (just by saying 'throw')
# function bla function bla(){ try{ # this will fail, it's not a real command blaaaa }catch{ write-host ("[{0}] Failed to blaaaa" -f $MyInvocation.MyCommand) -ForegroundColor cyan throw } } # wrapper function blabla function blabla(){ try{ bla bla }catch{ write-host ("[{0}] Failed to blabla" -f $MyInvocation.MyCommand) -ForegroundColor cyan throw } } # main code try{ blabla }catch{ write-host "Ultimately failed in blabla" -ForegroundColor cyan # if you rethrow again, it will show the actual error # if you omit this final error, you will have done a full catch, having a trace but no error throw }
This is the new output
Which gives you a better stacktrace feeling.
[bla] Failed to blaaaa [blabla] Failed to blabla Ultimately failed in blabla blaaaa : The term 'blaaaa' is not recognized as the name of a cmdlet, function, script file, o r operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:5 char:9 + blaaaa + ~~~~~~ + CategoryInfo : ObjectNotFound: (blaaaa:String) [], ParentContainsErrorRecordEx ception + FullyQualifiedErrorId : CommandNotFoundException
I totally agree with you! Much better.
ReplyDelete