{"id":10851,"date":"2006-04-25T12:17:55","date_gmt":"2006-04-25T12:17:55","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2006\/04\/25\/debugging-monad-scripts-part-7-final-how-traps-work\/"},"modified":"2019-02-18T13:25:04","modified_gmt":"2019-02-18T20:25:04","slug":"debugging-monad-scripts-part-7-final-how-traps-work","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/debugging-monad-scripts-part-7-final-how-traps-work\/","title":{"rendered":"Debugging Monad Scripts, Part 7 (Final): How Traps Work"},"content":{"rendered":"<p>Did your command or script fail and\/or report an error?&nbsp; We hope to have a proper script debugger in a future version, but until then, MSH has some handy features to help you figure out what went wrong.&nbsp; In this series of blog entries, I will present some of those features.&nbsp; Thanks to Jim Truher [MSFT], Bruce Payette [MSFT], and Jeff Jones [MSFT] for their help in putting this together.<\/p>\n<p>See the Windows &#8220;Monad&#8221; Shell Beta 2 Documentation Pack (<a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=8a3c71d1-18e5-49d7-952a-c55d694ecee3&amp;displaylang=en\"><font color=\"#0000ff\">http:\/\/www.microsoft.com\/downloads\/details.aspx?FamilyID=8a3c71d1-18e5-49d7-952a-c55d694ecee3&amp;displaylang=en<\/font><\/a>) for general information about Monad.<\/p>\n<p>Part 1: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/04\/489138.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/04\/489138.aspx<\/font><\/a>&nbsp;(Terminating vs. Non-Terminating Errors, ErrorRecord)<br \/>Part 2: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/08\/490130.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/08\/490130.aspx<\/font><\/a>&nbsp;($error)<br \/>Part 3: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/09\/490625.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/09\/490625.aspx<\/font><\/a>&nbsp;(write-host)<br \/>Part 4: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/09\/491035.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/09\/491035.aspx<\/font><\/a>&nbsp;(set-mshdebug)<br \/>Part 5: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/11\/491967.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/11\/491967.aspx<\/font><\/a>&nbsp;(Preferences and Commandline Options)<br \/>Part 6: <a href=\"http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/15\/492769.aspx\"><font color=\"#0000ff\">http:\/\/blogs.msdn.com\/monad\/archive\/2005\/11\/15\/492769.aspx<\/font><\/a>&nbsp;(Trace-Expression, Breakpoint Script)<\/p>\n<p>Jon Newman [MSFT]<\/p>\n<p><font size=\"2\"><font size=\"3\"><\/font><\/font>&nbsp;<\/p>\n<p><font size=\"2\"><font size=\"3\"><b><font size=\"2\"><\/p>\n<p><font size=\"3\">How Traps Work<\/font><\/p>\n<p><\/b><\/p>\n<p><font size=\"3\">You can use the &#8220;trap&#8221; language feature to manage terminating errors in your script. &#8220;Getting Started.doc&#8221; and &#8220;MonadScripting-HandsOnLab.doc&#8221; from the Documentation Pack contain some details, but here is a little more detail.<\/font><\/p>\n<p><font size=\"3\">If you don&#8217;t use &#8220;trap&#8221; at all, terminating errors halt the command which is executing, and then the script moves on to the next command. In this example, you can see that the &#8220;terminating error&#8221; only terminates the command where it occurs, and execution continues with the next command, &#8220;ending a&#8221;.<\/font><\/p>\n<p><\/font><font face=\"Courier New\"><\/p>\n<p>MSH C:\\temp&gt; get-content .\\test.msh<br \/>function a<br \/>{<br \/>write-host &#8220;starting a&#8221;<br \/>write-host (1 \/ $null)<br \/>write-host &#8220;ending a&#8221;<br \/>}<br \/>write-host &#8220;starting main&#8221;<br \/>a<br \/>write-host &#8220;ending main&#8221;<br \/>MSH C:\\temp&gt; .\\test.msh<br \/>starting main<br \/>starting a<br \/>Attempted to divide by zero.<br \/>At C:\\temp\\test.msh:4 char:4<br \/>+ 1 \/ &lt;&lt;&lt;&lt; $null<br \/>ending a<br \/>ending main<br \/>MSH C:\\temp&gt; get-content .\\test.msh<\/p>\n<p><\/font><\/p>\n<p>You can add &#8220;trap&#8221; statements to your script to handle terminating errors. Inside the trap statement, &#8220;$_&#8221; is the ErrorRecord for the error, and you can use &#8220;break;&#8221; to break script execution, or &#8220;continue;&#8221; to continue with the next command after the one which hit the error.<\/p>\n<p><font face=\"Courier New\"><\/p>\n<p>MSH C:\\temp&gt; get-content .\\test.msh<br \/>function a<br \/>{<br \/>trap [System.DivideByZeroException] { write-host (&#8220;trapped &#8221; + $_.Exception.GetType().Name); continue; }<br \/>write-host &#8220;starting a&#8221;<br \/>write-host (1 \/ $null)<br \/>write-host &#8220;ending a&#8221;<br \/>}<br \/>write-host &#8220;starting main&#8221;<br \/>a<br \/>write-host &#8220;ending main&#8221;<br \/>MSH C:\\temp&gt; .\\test.msh<br \/>starting main<br \/>starting a<br \/>trapped DivideByZeroException<br \/>ending a<br \/>ending main<br \/>MSH C:\\temp&gt;<\/p>\n<p><\/font><\/p>\n<p>Here&#8217;s the tricky bit: If the current scope does not contain a trap, but any outer scope does, script execution after a terminating error will break out to the nearest scope where any trap (whether it matches the error or not) is defined. In this example, we move the trap statement out of &#8220;function a&#8221; and into the outer scope:<\/p>\n<p><font face=\"Courier New\"><\/p>\n<p>MSH C:\\temp&gt; get-content .\\test.msh<br \/>trap [System.DivideByZeroException] { write-host (&#8220;trapped &#8221; + $_.Exception.GetType().Name); continue; }<br \/>function a<br \/>{<br \/>write-host &#8220;starting a&#8221;<br \/>write-host (1 \/ $null)<br \/>write-host &#8220;ending a&#8221;<br \/>}<br \/>write-host &#8220;starting main&#8221;<br \/>a<br \/>write-host &#8220;ending main&#8221;<br \/>MSH C:\\temp&gt; .\\test.msh<br \/>starting main<br \/>starting a<br \/>trapped DivideByZeroException<br \/>ending main<br \/>MSH C:\\temp&gt;<\/p>\n<p><\/font><\/p>\n<p>Note that &#8220;ending a&#8221; doesn&#8217;t appear in the output; execution broke out of function a.<\/p>\n<p>This applies whether or not the error which occurred matches the exception you are trapping:<\/p>\n<p><font face=\"Courier New\"><\/p>\n<p>MSH C:\\temp&gt; get-content .\\test.msh<br \/>trap [System.ArgumentException] { write-host (&#8220;trapped &#8221; + $_.Exception.GetType().Name); continue; }<br \/>function a<br \/>{<br \/>write-host &#8220;starting a&#8221;<br \/>write-host (1 \/ $null)<br \/>write-host &#8220;ending a&#8221;<br \/>}<br \/>write-host &#8220;starting main&#8221;<br \/>a<br \/>write-host &#8220;ending main&#8221;<br \/>MSH C:\\temp&gt; .\\test.msh<br \/>starting main<br \/>starting a<br \/>Attempted to divide by zero.<br \/>At C:\\temp\\test.msh:6 char:4<br \/>+ 1 \/ &lt;&lt;&lt;&lt; $null<br \/>ending main<br \/>MSH C:\\temp&gt;<\/p>\n<p><\/font><\/p>\n<p>You may ask, why is this? Remember that trap statements operate in the scope in which they are declared. We had implementation and performance problems in exiting the &#8220;function a&#8221; scope, running the trap block in the outer scope, then returning to the &#8220;function a&#8221; scope.<\/p>\n<p><\/font><\/font><\/p>\n<p>[<i>Edit: Monad has now been renamed to Windows PowerShell.  This script or discussion may require slight adjustments before it applies directly to newer builds.<\/i>]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Did your command or script fail and\/or report an error?&nbsp; We hope to have a proper script debugger in a future version, but until then, MSH has some handy features to help you figure out what went wrong.&nbsp; In this series of blog entries, I will present some of those features.&nbsp; Thanks to Jim Truher [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-10851","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>Did your command or script fail and\/or report an error?&nbsp; We hope to have a proper script debugger in a future version, but until then, MSH has some handy features to help you figure out what went wrong.&nbsp; In this series of blog entries, I will present some of those features.&nbsp; Thanks to Jim Truher [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=10851"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10851\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=10851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=10851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=10851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}