How to use PowerShell Try, Catch and the Write-Verbose and Write-Debug

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in this video i want to dive into the try catch error handling inside our powershell scripts and also have a quick look at the right verbose right debug that might help us day to day as always if this is useful a like subscribe comment and share is appreciated hit that bell icon to get notified i'm going to start doing more community interactions so if you subscribed you'll be able to see those so i really just want to dive into what happens when we get some error actually in our powershell so if we jump over to vs code firstly the docs are great the whole exception documentation is phenomenal i'm going to link to that in the description definitely take a look at that but let's start off just looking at a regular error let's say i go and get some content from a path that doesn't actually exist and we can see hey cannot find the drive because there's error down the bottom a drive with the name r does not exist now i could also just throw my own error using the throw command but before i do that well i can look at what the last error was i can do get error now when we run get error we can see a whole bunch of information hey i can see i got this drive not found exception down here i can also see information about the target object the category the item name the target the stack trace message that's a very useful one that we can actually call on and get the detail around and the source so system management dot automation huge amounts of info available it also writes that to dollar error now this is kind of cumulative so i can see it adds it to this variable for my session so if i went and through my own error if i jump up okay so exception john's error well i can still do get error again and it's going to show me hey john's error but now if i look at the error variable i can see two errors i can see hey the last error was john's error and then there was this hey get content the one before but really we want to try and handle this a different way now i can write errors to my own custom variable so here you can see all i've added is error variable bad things so now if i run this same error but now i can actually look at bad things and hey look there's the error for that command i ran i could even write code to check well does it actually have anything in it and here you can say okay well if there is something i is not null then you can see here hey look foreground blue background white had an issue and then you can actually see i'm diving into the exception part of the error and getting the message component which in this case was the cannot find drive a drive with the name r does not exist so i can do things with the error variables and note this little script here is in my github repo and again i've linked to that in the description as well but the better option is to actually use a try catch hey i want to try and do something and then if there's an error catch it and do something specific in this piece of code so what i'm going to try now is hey i'm wrapping what i want to do in the try so in this case what i want to try is get content on this path i know it doesn't exist now if there's an exception then it will call my catch block of code here something went wrong so let's try that execute um why don't actually think that worked it just gave me the same standard kind of error i don't see my something went wrong line so why didn't that work the reason is try catch catches a terminating error whereas that path not found is not a terminating error so let's do a try catch this time calling just complete garbage that means it's terminating it's going to cause a problem and i should see no idea what that was and sure enough i do hey i can see in my output down the bottom no idea what that was because it was terminating now if i ordinarily just run that one line i get this whole set of things so somehow i need to make those commands that aren't normally terminating a terminating i a stop event so what i'm going to do here is i can add to the end of my regular powershell commands an error action so i'm going to say error action stop so that now makes it terminating so if i try this block of code again and all i've changed is added the error action stop well now it doesn't output the regular error now it outputs my something went wrong that command executing now has an error action of stop ie terminating so my catch can well catch it now there are different types of error actions in my case i had it to stop but if we just actually delete this for a second and we kind of just type error and let me just start typing something so i can see hey look there's silently continue there's stop there's suspend there's a whole bunch of different options to me so i'm actually going to do this time silently continue so let's see what happens when i run this so there's no error but it did still error it just silently continued if i do get error i can see it's still there it's still that hey drive not found i can still see hey not there 42 proving it actually was this error that is actually causing this but it just silently carried on so this is just kind of a note that there are different types of error action now i can absolutely look at the details of that error so this time instead of just writing some hey i fell over and i can't get up we're actually going to get the error message now we can use the dollar underscore that's the same as dollar ps item i'm going to look at the exception and the message i'm going to store that in this error message variable so instead of having that kind of glaring output it normally gives i can now control that so what i'm going to do is write output hey something went wrong in the message then i'm going to use write host just so i can do some different formatting to output the entire exception and then also to demonstrate i can use ps item instead of dollar underscore i'm going to output the invocation info ie the information that led up to actually having this where the calls came from so now if i take this and execute we had a whole bunch of different information let's make this a bit bigger for a second so firstly okay we get our something went wrong and then it added the message then we can see here i've actually got my exception with my blue on white output and then i can see that invocation info the invocation name pipeline length i can see all the things that actually led up to that so i get that full set of information so this is where it gets really powerful that hey i can use the exception i can get the details of the exception there's all different components actually to that exception and the documentation goes into huge details about this now potentially i may want to do different things depending on the type of error so what i can actually do is have different types of catch so here i've got this gobbledygook error so this is going to be a command not found so notice here i've got a catch if it is command not found and then i've got kind of a default catch for everything else so if i do the try catch here calling my non-existent command hey no idea what this command is that's the output i get because it was a command not found exception i don't get it just outputting the overall exception so i can do some really nice things in here to actually work out hey i might get different types of exception i want to do different things so i can use that with the actual type of exception i see now what if i can't use that error action stop so there's actually an error action preference this is a variable and if we look at this we can see the default for my environment is continue down here on the bottom so i can see here my action preference is just continue so what we could actually do if we're in a situation where maybe i can't set the error action to stop maybe i'm calling saying outside of powershell what i could actually do is i could change the default error action preference to stop now i want to be careful with this i don't want to just set it to a new value and then just carry on so what i would do is i'd want to store the current value do whatever i want to do after i've set it to what i want i stop and then put it back which is what we're going to do in this script so what we're going to do here is as we can see the first thing is we're going to capture the current value into a current error action preference then i'm going to set it to what i want it to be i stop and i'm doing that regular get content command but notice i don't have the dash error action at the end of it now i have a catch something went wrong write out the message but then i need to put it back no matter what whether it failed or not i have to set the error action preference back to what it was before so this is where we use finally so what finally lets us do is error or not this code will always run so finally set the error action preference back to what it was originally ie that current error action preference variable i created where i copied in the original value so i'm going to set it back so let's kind of see this little part in action so if i just run this so it it got cool even though i didn't do the error action stop because i set the default and it outputted in my formatting hey the message with that blue on white but if i actually look at my error action preference it's still continue it all got set back so if i have a scenario where i can't do error action stop i want to still handle that in my try catch then i can set the error action preference but make sure you set it back afterwards now just a little note if i'm calling let's say something from cmd.exe so here i'm using invoke expression and i'm saying hey i want to call command xe i want it to run the command c dir on that no existent file so if i capture that output notice the output edit to screen the error is actually on my screen system cannot find the path specified if i look at my variable no error this is because in the command environment there's two actually many different outputs but standard out is number one standard error is number two so if i want to catch the errors as well i can redirect 2 to 1. i.e standard error go to standard out so now if i execute this notice nothing went to screen and my variable to capture the output now has that error in it so that was kind of just a few little things around actually levering jing that try catch um and it's not complicated i can just have those different blocks different types of catch depending on what i wanted now when to finish on one other thing and that was kind of right output right verbose right debug um because i know when i started out and i still do sometimes if i hit a problem i quickly add in a right output in my code to try and see where it may be a logic path it's going try and see what the variables are and if i want to see the variables really i should just be debugging and then i can add watches on variables but maybe hey i just want some information or maybe instead of commenting my code which often gets overlooked and doesn't get updated maybe i want to be able to run it and actually have more output in certain scenarios maybe there's a problem i want to see different types of information and rather than adding in commands and comment in the mail and adding them right verbose and right debug can be super super powerful so in this case i'm just going to have a function now this function is just gonna it's sad it's gonna create a random number and then depending on the number i output from that randomization it's gonna output one of three kind of good morning messages england america who knows what so if i just define this function so i've defined the function i can now do get random message sad good morning to thee so that would based on the code tell me the number was um greater or equal to four and less than seven so four five or six but maybe this was a far more complicated script it's obviously super super simple i would like to kind of maybe see more information or see debugging information depending on what i was doing so now i've got a different version of this and there's really just three things the first is i'm adding command lit binding now what this does is it gives me the ability to use things like dash verbose dash debug because if i look at my get random message sad and do dash i'm hitting tab there is nothing i can't do anything so commandlet binding is going to add those for me i'm still just going to maybe look at if their parameters i don't have any but now what i'm doing is right verbose generating a random number right verbose number is i'm outputting what the value of the variable is just give me some extra info and now maybe if i'm was having problems in the future or whatever that is now i've got a right debug start of switch statement then i've added to the end of each of my statements i've used a semicolon rather than doing multiple lines hey my logic part which logic gate did it go to hey this is less than four then i've got hey between four and six and then hey the default so if i define this function by just again calling this little bit of code here so that's done so if i do get random message firstly if well let's just run it now it says no extra output it just runs exactly as we would expect now if i do upper undo dash and tab suddenly i have these options arguments verbose debug i have these other things that i can now do because of that command lit binding and if we do it for both let's just do dash verbose hey okay it's generating a random number the number is eight then top of the morning so it only shows me that if i add that dash for bose to the execution maybe i'm having problems i don't understand which logic path is going down so i could add dash debug okay start the switch statement so i know it's going into that flow good morning to the oh it was debug four to six okay that helps i know where it is in my code i could absolutely combine those things i could do debug and verbose so hey generating random number number is eight starting the switch statement okay it went to the default so obviously the default was the seven eight nine ten so those helped me much more than me just hey on this original script i had at the top saying oh i'm curious what's going on okay let's just add in a right output number okay well then it works i'll delete it or i'll comment that thing out and if i needed it again i would uncomment it it's just kind of ugly and i really don't want to be in that world so the use of the right verbose and the right debug are super super powerful to actually help us when we're trying to troubleshoot things uh when we maybe want just more information about things if it's more complicated maybe there's a whole bunch of internal information that normally we don't care about but maybe hey someone does care well we could output it if they wanted that extra information whereas the debug is more hey look maybe i'm trying to track the flow or maybe i'm trying to see some variables inside i could output that information to help when there are things going wrong and rather than having to change the script i can say okay run this commander with dash debug and then it gives me the information i would need to work out hey exactly why is this behaving the way it's behaving so that was it i hope that was useful again in the description below i've got the link to these two files if you wanted to play around with them but until next time take care you
Info
Channel: John Savill's Technical Training
Views: 19,985
Rating: undefined out of 5
Keywords: powershell, error handling, write-debug, write-verbose, try catch, debug
Id: 2eByC9N1xIQ
Channel Id: undefined
Length: 19min 23sec (1163 seconds)
Published: Tue May 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.