{"id":72082,"date":"2015-07-18T00:01:00","date_gmt":"2015-07-18T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/07\/18\/weekend-scripter-break-in-to-a-script-via-a-command\/"},"modified":"2019-02-18T09:46:57","modified_gmt":"2019-02-18T16:46:57","slug":"weekend-scripter-break-in-to-a-script-via-a-command","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-break-in-to-a-script-via-a-command\/","title":{"rendered":"Weekend Scripter: Break in to a Script via a Command"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Ed Wilson, Microsoft Scripting Guy, talks about using the debugger to break in to a script via a specific command.<\/span>\nMicrosoft Scripting Guy, Ed Wilson, is here. One of the cool things, when troubleshooting a specific function in Windows PowerShell, is to set a breakpoint to occur each time the command is called. Remember, Windows PowerShell functions are also Windows PowerShell commands, just as language statements and cmdlets are.<\/p>\n<p class=\"Normalunindented\">To set the breakpoint in a command, you use the <b>-command<\/b> parameter. You can break on a call to a Windows PowerShell cmdlet, function, or external script. You can use aliases when setting breakpoints. When you create a breakpoint on an alias for a cmdlet, the debugger will only stop on the use of the alias&mdash;not on the actual command name.<\/p>\n<p class=\"Normalunindented\">In addition, you do not have to specify a script for the debugger to break. If you do not type a path to a script, the debugger will be active for everything within the Windows PowerShell console session. Every occurrence of the <b>Foreach<\/b> command will cause the debugger to break. The command to set such a breakpoint is shown here:<\/p>\n<p style=\"margin-left:30px\">Set-PSBreakpoint -Command Foreach<\/p>\n<p class=\"Normalunindented\">Because <b>Foreach<\/b> is a language statement in addition to an alias for the <b>Foreach-Object<\/b> cmdlet, you might wonder whether the Windows PowerShell debugger will break on the language statement and on the use of the alias for the cmdlet. The answer is no.<\/p>\n<p class=\"Normalunindented\">You can set breakpoints on language statements, but the debugger will not break on a language statement. As shown here, the debugger breaks on the use of the <b>Foreach<\/b> alias, but not on the use of the <b>Foreach-Object<\/b> cmdlet or the <b>%<\/b> alias:<\/p>\n<p class=\"CodeBlock\" style=\"margin-left:30px\">PS C:\\&gt; 1..3 | Foreach-Object {$_}<br \/> 1<br \/> 2<br \/> 3<br \/> PS C:\\&gt; 1..3 | % {$_}<br \/> 1<br \/> 2<br \/> 3<br \/> PS C:\\&gt; 1..3 | foreach {$_}<br \/> Hit Command breakpoint on &#8216;foreach&#8217;<\/p>\n<p> At line:1 char:1<br \/> + 1..3 | foreach {$_}<br \/> + ~~~~~~~~~~~~~~~~~~~<br \/> [DBG]: PS C:\\&gt;&gt; c<br \/> 1<br \/> 2<br \/> 3<br \/> PS C:\\&gt;<\/p>\n<p class=\"Readeraidonly\"><b>Note<\/b>&ensp;You can use the shortcut technique of creating the breakpoint for the Windows PowerShell session and not specifically for the script. By leaving out the <b>-script<\/b> parameter when creating a breakpoint, you cause the debugger to break in to any running script that uses the named function. This allows you to use the same breakpoints when debugging scripts that use the same function.<\/p>\n<p class=\"Readeraidonly\">When creating a breakpoint for the <b>DivideNum<\/b> function that is used in the C:\\FSO\\BadScript.ps1 script, you can leave off the path to the script, because only this script uses the <b>DivideNum<\/b> function.<\/p>\n<p class=\"Readeraidonly\">This makes the command easier to type, but it could become confusing if you&rsquo;re looking through a collection of breakpoints. If you are debugging multiple scripts in a single Windows PowerShell console session, it could become confusing if you do not specify the script to which the breakpoint applies&mdash;unless, of course, you are specifically debugging the function as it is used in multiple scripts.<\/p>\n<p class=\"Readeraidonly\">Creating a command breakpoint for the <b>DivideNum<\/b> function is shown here:<\/p>\n<p class=\"CodeBlock\" style=\"margin-left:30px\">PS C:\\&gt; Set-PSBreakpoint -Command DivideNum<\/p>\n<p> &nbsp; ID Script&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Line Command&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Variable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Action<br \/> &nbsp; &#8212; &#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;- &nbsp; &nbsp; &nbsp; &#8212;&#8212;- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#8212;&#8212;&#8211; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#8212;&#8212;<br \/> &nbsp;&nbsp; 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DivideNum\nWhen you run the script, it hits a breakpoint when the <b>DivideNum<\/b> function is called. When BadScript.ps1 hits the <b>DivideNum<\/b> function, the value of <b>$num<\/b> is 0. As you step through the <b>DivideNum<\/b> function, you assign a value of 2 to the <b>$num<\/b> variable, a result of 6 is displayed, and then the <b>12\/$num<\/b> operation is carried out.\nNext, the <b>AddOne<\/b> function is called and the value of <b>$num<\/b> once again becomes 0. When the <b>AddTwo<\/b> function is called, the value of <b>$num<\/b> also becomes 0. This is shown here:<\/p>\n<p class=\"CodeBlock\" style=\"margin-left:30px\">PS C:\\&gt; C:\\fso\\BadScript.ps1<br \/> Hit Command breakpoint on &#8216;DivideNum&#8217;<\/p>\n<p> At C:\\fso\\BadScript.ps1:37 char:1<br \/> + {<br \/> + ~<br \/> [DBG]: PS C:\\&gt;&gt; s<br \/> At C:\\fso\\BadScript.ps1:38 char:2<br \/> +&nbsp; 12\/$num<br \/> +&nbsp; ~~~~~~~<br \/> [DBG]: PS C:\\&gt;&gt; $num<br \/> 0<br \/> [DBG]: PS C:\\&gt;&gt; $num=2<br \/> [DBG]: PS C:\\&gt;&gt; s<br \/> 6<br \/> At C:\\fso\\BadScript.ps1:39 char:1<br \/> + } #end function DivideNum<br \/> + ~<br \/> [DBG]: PS C:\\&gt;&gt; s<br \/> At C:\\fso\\BadScript.ps1:45 char:1<br \/> + AddOne($num) | AddTwo($num)<br \/> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~<br \/> [DBG]: PS C:\\&gt;&gt; $num<br \/> 0<br \/> [DBG]: PS C:\\&gt;&gt; s<br \/> At C:\\fso\\BadScript.ps1:12 char:1<br \/> + {<br \/> + ~<br \/> [DBG]: PS C:\\&gt;&gt; q<br \/> PS C:\\&gt;<\/p>\n<h2>Responding to breakpoints<\/h2>\n<p class=\"Normalunindented\">When the script reaches a breakpoint, control of the Windows PowerShell console is turned over to you. Inside the debugger, you can type any legal Windows PowerShell command, and even run cmdlets such as <b>Get-Process<\/b> or <b>Get-Service<\/b>.<\/p>\n<p class=\"Normalunindented\">In addition, there are several new debugging commands that can be typed into the Windows PowerShell console when a breakpoint has been reached. The available debug commands are shown in the following table.<\/p>\n<h4 class=\"TableNum-Title\">Windows PowerShell debugging commands<\/h4>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"138\" valign=\"bottom\">\n<p class=\"TableHead\"><b>Keyboard shortcut<\/b><\/p>\n<\/td>\n<td width=\"138\" valign=\"bottom\">\n<p class=\"TableHead\"><b>Command name<\/b><\/p>\n<\/td>\n<td width=\"264\" valign=\"bottom\">\n<p class=\"TableHead\"><b>Command meaning<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">S<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Step-Into<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Executes the next statement and then stops.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">V<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Step-Over<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Executes the next statement, but skips functions and invocations. The skipped statements are executed, but not stepped through.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">O<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Step-Out<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Steps up one level in the current function, if nested. If in the main body, it continues to the end or the next breakpoint. The skipped statements are executed, but not stepped through.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">C<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Continue<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Continues to run until the script is complete or until the next breakpoint is reached. The skipped statements are executed, but not stepped through.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">L<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">List<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Displays the part of the script that is executing. By default, it displays the current line, 5 previous lines, and 10 subsequent lines. To continue listing the script, press ENTER.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">L &lt;M&gt;<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">List<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Displays 16 lines of the script, beginning with the line number specified by M.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">L &lt;M&gt; &lt;N&gt;<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">List<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Displays the number of lines of the script specified by N, beginning with the line number specified by M.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">Q<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Stop (Quit)<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Stops executing the script and exits the debugger.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">K<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Get-PsCallStack<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Displays the current call stack.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">ENTER<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Repeat<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Repeats the last command if it was <b>Step-Into<\/b>, <b>Step-Over<\/b>, or <b>List<\/b>. Otherwise, represents a submit action.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\" align=\"center\">H or ?<\/p>\n<\/td>\n<td width=\"138\" valign=\"top\">\n<p class=\"TableText\">Help<i><\/i><\/p>\n<\/td>\n<td width=\"264\" valign=\"top\">\n<p class=\"TableText\">Displays the debugger command Help.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-size:12px\">That wraps up Debugging Week. I invite you to follow me on <\/span><a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\" style=\"font-size:12px\">Twitter<\/a><span style=\"font-size:12px\"> and <\/span><a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" style=\"font-size:12px\">Facebook<\/a><span style=\"font-size:12px\">. If you have any questions, send email to me at <\/span><a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\" style=\"font-size:12px\">scripter@microsoft.com<\/a><span style=\"font-size:12px\">, or post your questions on the <\/span><a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\" style=\"font-size:12px\">Official Scripting Guys Forum<\/a><span style=\"font-size:12px\">. See you tomorrow. Until then, peace.<\/span><\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Ed Wilson, Microsoft Scripting Guy, talks about using the debugger to break in to a script via a specific command. Microsoft Scripting Guy, Ed Wilson, is here. One of the cool things, when troubleshooting a specific function in Windows PowerShell, is to set a breakpoint to occur each time the command is called. Remember, [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[602,3,4,61,45],"class_list":["post-72082","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-debugger","tag-scripting-guy","tag-scripting-techniques","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Ed Wilson, Microsoft Scripting Guy, talks about using the debugger to break in to a script via a specific command. Microsoft Scripting Guy, Ed Wilson, is here. One of the cool things, when troubleshooting a specific function in Windows PowerShell, is to set a breakpoint to occur each time the command is called. Remember, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/72082","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\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=72082"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/72082\/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=72082"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=72082"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=72082"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}