{"id":51023,"date":"2010-03-11T00:01:00","date_gmt":"2010-03-11T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/03\/11\/hey-scripting-guy-how-can-i-use-trycatchfinally-in-windows-powershell\/"},"modified":"2010-03-11T00:01:00","modified_gmt":"2010-03-11T00:01:00","slug":"hey-scripting-guy-how-can-i-use-trycatchfinally-in-windows-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-use-trycatchfinally-in-windows-powershell\/","title":{"rendered":"Hey, Scripting Guy! How Can I Use Try\/Catch\/Finally in Windows PowerShell?"},"content":{"rendered":"<p class=\"MsoNormal\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\">&nbsp;<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\">Hey, Scripting Guy! One thing I miss in Windows PowerShell is the ability to use a <b>Try\/Catch\/Finally<\/b> block that I can use in C#. To me it is an elegant solution to error handling. You attempt something, catch any resulting errors, and clean up the mess you made. Are there any plans in Windows PowerShell 3.0 to introduce this kind of structured error handling? I know there is the <b>Trap<\/b> statement, but that is weak in comparison to <b>Try\/Catch\/Finally<\/b>. <\/p>\n<\/p>\n<p class=\"MsoNormal\">&#8212; JK<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello JK, <\/p>\n<p class=\"MsoNormal\">Microsoft Scripting Guy Ed Wilson here. Today I will be interviewed by the people from the Get-Scripting podcast. It will be pretty cool, and we will talk about Windows PowerShell best practices, as well as the 2010 Scripting Games that begin April 26, 2010. I have meetings both before and after the podcast, so this morning is the only time I have to check <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> e-mail, make a few tweets, and post to Facebook. The rest of the day is pretty much a goner. I am drinking a rather indifferent black tea that I spiced up with a little bit of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Anise\"><font face=\"Segoe\">anise<\/font><\/a>. It is actually pretty good this way, although I do not think it will become part of my regular repertoire. <\/p>\n<p class=\"MsoNormal\">JK, you do not need to wait for Windows PowerShell 3.0 to come out, because <a href=\"http:\/\/support.microsoft.com\/kb\/968929\"><font face=\"Segoe\">Windows PowerShell 2.0<\/font><\/a>, which is installed on both Windows 7 and Windows Server 2008 R2, includes <b>Try\/Catch\/Finally<\/b> today. <\/p>\n<p class=\"MsoNormal\">When using a <b>Try\/Catch\/Finally<\/b> block, the command you wish to execute is placed in the <b>Try<\/b> block. If an error occurs when the command executes, the error will be written to the <b>$Error<\/b> variable, and script execution moves to the <b>Catch<\/b> block. The TestTryCatchFinally.ps1 script uses the <b>Try<\/b> command to attempt to create an object. A string states that the script is attempting to create a new object. The object to create is stored in the <b>$ob1<\/b> variable. The <b>New-Object <\/b>cmdlet creates the object. After the object has been created and stored in the <b>$a<\/b> variable, the members of the object are displayed via the <b>Get-Member<\/b> cmdlet. This code illustrates the technique:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Try<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;Attempting to create new object $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a = new-object $ob1<br \/><span>&nbsp;&nbsp; <\/span>&#8220;Members of the $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>&#8220;New object $ob1 created&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a | Get-Member<br \/><span>&nbsp;<\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Use the <b>Catch<\/b> block to capture errors that occurred during the <b>Try<\/b> block. You can specify the type of error to catch, as well as the action you wish to perform when the error occurs. In the TestTryCatchFinally.ps1 script, I monitor for <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.exception.aspx\"><font face=\"Segoe\">System.Exception<\/font><\/a> errors. The <b>System.Exception<\/b> .NET Framework class is the base class from which all other exceptions derive. This means a <b>System.Exception<\/b> is as generic as you can get; in essence, it will capture all predefined, common, system runtime exceptions. Upon catching the error, you can then specify what code you would like to execute. In this example, I display a single string that states that the script caught a system exception. The <b>Catch<\/b> block is shown here: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Catch<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>[system.exception]<br \/><span>&nbsp; <\/span>&#8220;caught a system exception&#8221;<br \/><span>&nbsp;<\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The <b>Finally<\/b> block of a <b>Try\/Catch\/Finally<\/b> sequence always runs, regardless if an error is generated or not. This means that any code cleanup you wish to do, such as explicitly releasing COM objects, should be placed in a <b>Finally<\/b> block. In the TestTryCatchFinally.ps1 script, the <b>Finally<\/b> block displays a string that states the script has ended. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">Finally<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;end of script&#8221;<br \/><span>&nbsp;<\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The complete TestTryCatchFinally.ps1 script is seen here.<\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>TestTryCatchFinally.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$ob1 = &#8220;kenobie&#8221;<br \/>&#8220;Begin test&#8221;<\/p>\n<p>Try<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;Atte\nmpting to create new object $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a = new-object $ob1<br \/><span>&nbsp;&nbsp; <\/span>&#8220;Members of the $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>&#8220;New object $ob1 created&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a | Get-Member<br \/><span>&nbsp;<\/span>}<br \/>Catch [system.exception]<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;caught a system exception&#8221;<br \/><span>&nbsp;<\/span>}<br \/>Finally<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;end of script&#8221;<br \/><span>&nbsp;<\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">When the TestTryCatchFinally.ps1 script runs and the value of <b>$ob1<\/b> is equal to &ldquo;kenobie,&rdquo; an error occurs because there is no object named &ldquo;kenobie&rdquo; that is creatable via the <b>New-Object<\/b> cmdlet. The following image displays the output from the script.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of output of TestTryCatchFinally.ps1\" alt=\"Image of output of TestTryCatchFinally.ps1\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0311\/hsg-03-11-10-01.jpg\" width=\"600\" height=\"430\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">As seen in the previous image, the &ldquo;Begin Test&rdquo; string displays because it is outside the <b>Try\/Catch\/Finally<\/b> loop. Inside the <b>Try<\/b> block, the string &ldquo;Attempting to create new object kenobie&rdquo; is displayed because it comes before the <b>New-Object<\/b> command. This illustrates that the <b>Try<\/b> block is always attempted. The members of the &ldquo;kenobie&rdquo; object are not displayed, nor are the string &ldquo;new object kenobie created.&rdquo; This indicates that after the error is generated, the script moves to the next block.<\/p>\n<p class=\"MsoNormal\">In the <b>Catch<\/b> block, the <b>System.Exception<\/b> error is caught and displayed. The string &ldquo;caught a system exception&rdquo; is also displayed. Next, the script moves to the <b>Finally<\/b> block, and the &ldquo;end of script&rdquo; string is displayed. <\/p>\n<p class=\"MsoNormal\">If the script is run with the value of <b>$ob1<\/b> equal to &ldquo;system.object&rdquo; (which is a valid object), the <b>Try<\/b> block completes successfully. As seen in the following image, the members of the object are displayed, and the string that states the object was successfully created is also displayed. The <b>Catch<\/b> block is not entered, but the &ldquo;end of script&rdquo; string from the <b>Finally<\/b> block is displayed. <\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of object created and members displayed\" alt=\"Image of object created and members displayed\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0311\/hsg-03-11-10-02.jpg\" width=\"600\" height=\"430\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">You can have multiple <b>Catch<\/b> blocks in a <b>Try\/Catch\/Finally<\/b> block. The thing to keep in mind is that when an exception occurs, Windows PowerShell leaves the <b>Try<\/b> block and searches for the <b>Catch<\/b> block. The first <b>Catch<\/b> block that matches the exception that was generated will be used. Therefore, you want to use the most specific exception first, and then move to the more generic exceptions. This is seen in TestTryMultipleCatchFinally.ps1. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>TestTryMultipleCatchFinally.ps1<\/p>\n<p><\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$ob1 = &#8220;foo&#8221;<br \/>&#8220;Begin test&#8221;<br \/>$ErrorActionPreference = &#8220;stop&#8221;<br \/>Try<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>Get-Content foo<br \/><span>&nbsp; <\/span>&#8220;Attempting to create new object $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a = new-object $ob1<br \/><span>&nbsp;&nbsp; <\/span>&#8220;Members of the $ob1&#8221;<br \/><span>&nbsp;&nbsp; <\/span>&#8220;New object $ob1 created&#8221;<br \/><span>&nbsp;&nbsp; <\/span>$a | Get-Member<br \/><span>&nbsp;<\/span>}<br \/>Catch [System.Management.Automation.PSArgumentException]<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;invalid object&#8221;<br \/><span>&nbsp;<\/span>}<br \/>Catch [system.exception]<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;caught a system exception&#8221;<br \/><span>&nbsp;<\/span>}<br \/>Finally<br \/><span>&nbsp;<\/span>{<br \/><span>&nbsp; <\/span>&#8220;end of script&#8221;<br \/><span>&nbsp;<\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">The next image displays the output when running the TestTryMultipleCatchFinally.ps1 script. Two changes are made: The <b>$ErrorActionPreference<\/b> command is commented out as is the <b>Get-Content foo<\/b> command. Therefore, the error that will be generated is the one raised when attempting to create a nonexistent object. To find the specific error, I examined the <b>$error<\/b> variable after running the offending command. The error is found in the <b>Exception<\/b> field. The specific error that is raised is an instance of the <b>System.Management.Automation.PSArgumentException<\/b> error. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">PS C:&gt; $error | fl * -f<\/p>\n<p>PSMessageDetails<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>:<br \/>Exception<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: System.Management.Automation.PSArgumentException: Cannot find type [foo]: make sure the assembly containing this type is loaded. at System.Management.Automation.MshCommandRuntime.ThrowTerminatingError(ErrorRecord errorRecord)<br \/>TargetObject<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>:<br \/>CategoryInfo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: InvalidType: (:) [New-Object], PSArgumentException<br \/>FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand<br \/>ErrorDetails<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>:<br \/>InvocationInfo<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>: System.Management.Automation.InvocationInfo<br \/>PipelineIterationInfo : {0, 0}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of output of TestTryMultipleCatchFinally.ps1\" alt=\"Image of output of TestTryMultipleCatchFinally.ps1\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0311\/hsg-03-11-10-03.jpg\" width=\"600\" height=\"430\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">If a script has multiple errors and the error action preference is set to stop, the first error will cause the script to fail. By removing the comments from the <b>$ErrorActionPreference<\/b> line and the <b>Get-Content<\/b> line, the first error to be generated will be caught by the <b>System.Exception<\/b> <b>Catch<\/b> block and will therefore skip the argument exception. This is seen in the following image.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of first error caught by System.Exception Catch block\" alt=\"Image of first error caught by System.Exception Catch block\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2010\/march\/hey0311\/hsg-03-11-10-04.jpg\" width=\"600\" height=\"430\"><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">JK that is all there is to using <b>Try\/Catch\/Finally<\/b>. Join us tomorrow for Quick-Hits Friday. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\"><font face=\"Segoe\">Twitter<\/font><\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\"><span><font face=\"Segoe\">Facebook<\/font><\/span><\/a>. If you have any questions, send e-mail to us at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\"><font face=\"Segoe\">Official Scripting Guys Forum<\/font><\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p>&nbsp;<\/p>\n<p><\/span><\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p><b><span><\/span><\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; Hey, Scripting Guy! One thing I miss in Windows PowerShell is the ability to use a Try\/Catch\/Finally block that I can use in C#. To me it is an elegant solution to error handling. You attempt something, catch any resulting errors, and clean up the mess you made. Are there any plans in [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[68,51,3,4,45],"class_list":["post-51023","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-error-handling","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; &nbsp; Hey, Scripting Guy! One thing I miss in Windows PowerShell is the ability to use a Try\/Catch\/Finally block that I can use in C#. To me it is an elegant solution to error handling. You attempt something, catch any resulting errors, and clean up the mess you made. Are there any plans in [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51023","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=51023"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51023\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=51023"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=51023"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=51023"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}