{"id":82016,"date":"2017-02-06T00:01:32","date_gmt":"2017-02-06T08:01:32","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/?p=82016"},"modified":"2019-02-18T09:10:11","modified_gmt":"2019-02-18T16:10:11","slug":"debugging-powershell-script-in-visual-studio-code-part-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/debugging-powershell-script-in-visual-studio-code-part-1\/","title":{"rendered":"Debugging PowerShell script in Visual Studio Code \u2013 Part 1"},"content":{"rendered":"<p><strong>Summary<\/strong>: Here&#8217;s a look at the\u00a0<span>many features of the PowerShell debugger for Visual Studio Code.<\/span><\/p>\n<p>In previous blog posts, we covered <a target=\"_blank\" href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2016\/12\/05\/get-started-with-powershell-development-in-visual-studio-code\/\">how to get started with PowerShell development in Visual Studio Code<\/a> and the <a target=\"_blank\" href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2017\/01\/12\/visual-studio-code-editing-features-for-powershell-development-part-2\/\">editing features of Visual Studio Code and the PowerShell extension<\/a>.\u00a0 If you don\u2019t already have Visual Studio Code configured with the PowerShell extension, read those blog posts to get caught up.<\/p>\n<p>In the first of this two-part series, we will cover the many features of the PowerShell debugger for Visual Studio Code.\u00a0 These features are provided by the PowerShell extension, or, more accurately, by the PowerShell Editor Services module which comes with the PowerShell extension.<\/p>\n<p>PowerShell Editor Services runs in a separate process and supplies both language and debugging services to Visual Studio Code via a JSON remote procedure call (RPC) protocol that\u2019s defined by Visual Studio Code. One advantage of this approach is that a crash of the PowerShell Editor Services process doesn\u2019t cause Visual Studio Code to crash. And, with the latest version of the PowerShell extension, you can simply restart the current PowerShell session without restarting Visual Studio Code to get going again.<\/p>\n<h2>First look at the PowerShell Debugger in Visual Studio Code<\/h2>\n<p>Press Ctrl+Shift+P (Cmd+Shift+P on Mac) to open the PowerShell extension\u2019s <strong>Examples<\/strong> folder, type <strong>PowerShell open examples<\/strong>, and then press Enter. After the Examples folder has loaded, open the DebugTest.ps1 file, and set a breakpoint on the line that has the Start-Sleep command.\u00a0 To set the breakpoint, either click in the left editor margin or press F9 to toggle the breakpoint on and off for the current line.<\/p>\n<p>To open the Debug view, in the View Bar select <strong>Debug<\/strong> from the <strong>View<\/strong> menu or press Ctrl + Shift + D. In the <strong>Launch\u00a0Configuration<\/strong> dropdown (shown in the following screenshot), select the <strong>PowerShell Launch (current file)<\/strong> configuration. Like the PowerShell integrated scripting environment (ISE), this configuration will execute the file that\u2019s in the active editor window under the debugger when debugging is started.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1-HSG020617.png\" alt=\"Selecting the PowerShell Launch (current file) configuration\" width=\"544\" height=\"461\" class=\"alignnone size-full wp-image-82025\" \/><\/a><\/p>\n<p>Let\u2019s start a debug session. First, make sure the DebugTest.ps1 file\u2019s editor window is still the active window, and then press F5 or click the green <strong>Start Debugging<\/strong> button to the left of the Launch\u00a0Configuration dropdown (shown in the previous screenshot).<\/p>\n<p>After the debugger starts, you will see the Debug actions pane (shown in the following screenshot), and the debugger should pause at the breakpoint that you set.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2-HSG020617.png\" alt=\"Debug actions pane\" width=\"418\" height=\"68\" class=\"alignnone size-full wp-image-82035\" \/><\/a><\/p>\n<p>The Debug actions pane provides buttons for:<\/p>\n<ul>\n<li>Continue \/ Pause &#8211; F5<\/li>\n<li>Step Over &#8211; F10<\/li>\n<li>Step Into &#8211; F11<\/li>\n<li>Step Out &#8211; Shift + F11<\/li>\n<li>Restart &#8211; Ctrl + Shift + F5<\/li>\n<li>Stop &#8211; Shift + F5<\/li>\n<\/ul>\n<p>Now, let\u2019s look at the Debug view features that are available during a debug session.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3-HSG020617.png\" alt=\"Screenshot of debug session\" width=\"572\" height=\"430\" class=\"alignnone size-full wp-image-82045\" \/><\/a><\/p>\n<p>The <strong>VARIABLES<\/strong> section of the Debug view allows easy inspection of variable values. The <strong>Auto<\/strong> group weeds out the PowerShell automatic variables and leaves just the variables you\u2019ve defined and are likely interested in seeing. However, if the variable you are looking for isn\u2019t listed in <strong>Auto<\/strong>, you can look for it in the <strong>Local<\/strong>, <strong>Script<\/strong>, or <strong>Global<\/strong> groups.<\/p>\n<p>The <strong>WATCH<\/strong> section allows you to specify a variable or expression whose value should always be displayed.<\/p>\n<p>The <strong>CALL STACK<\/strong> section displays the call stack, and you can also select a different frame in the call stack to examine calling functions, scripts, and the variables that are defined in those scopes.<\/p>\n<p>The <strong>BREAKPOINTS<\/strong> section provides a central UI to manage, that is, create, disable, enable, and delete breakpoints that you may have defined over many different script files.<\/p>\n<p>You can also see from the previous screenshot that you get hover tips when you hold the cursor over a variable. Hover tips can show simple values, like numbers and strings, or complex objects as shown in the following screenshot:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4-HSG020617.png\" alt=\"Example of hover tips\" width=\"476\" height=\"500\" class=\"alignnone size-full wp-image-82055\" \/><\/a><\/p>\n<h2>VARIABLES section<\/h2>\n<p>The <strong>VARIABLES<\/strong> section allows you to inspect variable values, including complex variables such as those shown in the following screenshot:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5-HSG020617.png\" alt=\"Examining complex variables\" width=\"494\" height=\"514\" class=\"alignnone size-full wp-image-82065\" \/><\/a><\/p>\n<p>For primitive variable types, the value is displayed directly, typically as numbers, strings, and Booleans.\u00a0 For non-primitive variables, the type information is displayed. If the type is a collection or an array, the number of elements is displayed as well.<\/p>\n<p>You can do more than just inspect variable values. To change those values, double-click the value that you want to change, enter a new value, and click outside the edit box to complete the operation.<\/p>\n<p>You can enter arbitrary expressions when setting a variable\u2019s value, for example, <code>$itemCount+10<\/code> or <code>$null<\/code> or <code>$true<\/code>.\u00a0 Just remember, the expression has to be valid PowerShell syntax.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/6-HSG020617.png\" alt=\"Example of arbitrary expressions to setting a variable\u2019s value\" width=\"496\" height=\"124\" class=\"alignnone size-full wp-image-82075\" \/><\/a><\/p>\n<h2>Watch section<\/h2>\n<p>The <strong>WATCH<\/strong> section allows you to add a watch for any variable or expression. Simply click the <strong>+<\/strong> button (highlighted in the following screenshot), and type the variable name or a PowerShell expression:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7-HSG020617.png\" alt=\"The plus (+) button in the Watch section\" width=\"570\" height=\"247\" class=\"alignnone size-full wp-image-82085\" \/><\/a><\/p>\n<p>This values will always be evaluated, if possible. Keep in mind that the variables entered as a watch may not be available in all scopes.<\/p>\n<h2>BREAKPOINTS<\/h2>\n<p>Besides setting line breakpoints, the PowerShell debugger allows you to set function breakpoints, conditional breakpoints, and tracepoints.<\/p>\n<h3>Function breakpoints<\/h3>\n<p>Function breakpoints are effectively the same as a command breakpoint that you can set by using <code>Set-PSBreakpoint<\/code> with the <code>-Command<\/code> parameter. You can set a function breakpoint to break into the debugger not only on a particular function invocation but also on an alias, a built-in command, or application invocation.<\/p>\n<p>To set a function breakpoint, hover over the BREAKPOINTS section title bar, click the <strong>+<\/strong> button, type <code>Write-Output<\/code>, and then press Enter as shown in the following screenshot.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8-HSG020617-animation.gif\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8-HSG020617-animation.gif\" alt=\"Setting a break point\" width=\"354\" height=\"145\" class=\"alignnone size-full wp-image-82095\" \/><\/a><\/p>\n<p>Remove the line breakpoint that we set earlier on the line that executes the Start-Sleep command.<\/p>\n<p>Press F5 to start debugging the DebugTest.ps1 script, and you will see the debugger stop everywhere Write-Output is called. You can tell when the debugger is stopped on a function breakpoint by looking at the <strong>CALL STACK <\/strong>section of the Debug view. It will indicate that it is paused on a function breakpoint. The Debug Console will also indicate that a breakpoint has paused the debugger as shown in the following screenshot. If the Debug Console is not visible, select <strong>Debug Console<\/strong> from the <strong>View<\/strong> menu, or press Ctrl + Shift + Y.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/9-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/9-HSG020617-1024x139.png\" alt=\"Select Debug Console from the View menu\" width=\"1024\" height=\"139\" class=\"alignnone size-large wp-image-82105\" \/><\/a><\/p>\n<p>Stop debugging (press Shift + F5), and remove the function breakpoint by right-clicking it in the <strong>BREAKPONTS<\/strong> section, and selecting <strong>Remove breakpoint<\/strong>.<\/p>\n<h3>Conditional breakpoints<\/h3>\n<p>A conditional breakpoint is a line breakpoint that breaks into the debugger only when the line is executed <strong>and<\/strong> a user-supplied expression evaluates to $true. Conditional breakpoints are handy in scenarios where a line is executed many times, but you\u2019re interested in breaking into the debugger only when a certain \u201ccondition\u201d is true.<\/p>\n<p>Let\u2019s set a conditional breakpoint on the <code>$i = $i + 1<\/code> line in DebugTest.ps1. Right-click the line, and select <strong>Add Conditional Breakpoint\u2026<\/strong>. Enter the expression, $i % 10 -eq 0, as shown in the following screenshot, and then press Enter. As in the case with setting the value of a variable in the <strong>VARIABLES<\/strong> section, you have to use PowerShell syntax in the condition expression.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/10-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/10-HSG020617.png\" alt=\"Setting a conditional breakpoint\" width=\"533\" height=\"123\" class=\"alignnone size-full wp-image-82115\" \/><\/a><\/p>\n<p>After you set the breakpoint, you will see that conditional breakpoints are displayed with an \u201c<strong>=<\/strong>\u201d sign in the glyph:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/11-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/11-HSG020617.png\" alt=\"Display of conditional breakpoints\" width=\"459\" height=\"44\" class=\"alignnone size-full wp-image-82125\" \/><\/a><\/p>\n<p>When this expression evaluates to $true, the debugger will pause execution. Now press F5 to start debugging. You will notice the debugger stops when $i is 10, 20, 30, 40 and 50. Stop debugging (Shift + F5).<\/p>\n<h3>Tracepoints<\/h3>\n<p>Tracepoints allow you to emit information to the Debug Console (or change state in your script) without ever pausing the debugger. These are effectively the same as using Set-PSBreakpoint -Action {scriptblock} where the scriptblock tests for a certain condition, and if met, executes some script and then uses Continue to resume execution.<\/p>\n<p>Let\u2019s convert our previous conditional breakpoint to a tracepoint. Right-click the conditional breakpoint in the left editor margin, select <strong>Edit Breakpoint\u2026<\/strong>, and modify the condition to:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/12-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/12-HSG020617.png\" alt=\"Converting a conditional breakpoint to a tracepoint\" width=\"504\" height=\"56\" class=\"alignnone size-full wp-image-82135\" \/><\/a><\/p>\n<p>Press F5 to start debugging. You will notice that the script runs to completion without ever breaking into the debugger. In the Debug Console (Ctrl + Shift + Y), you will see the following output from this tracepoint:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/13-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/13-HSG020617.png\" alt=\"Display of output from the tracepoint in the Debug Console\" width=\"179\" height=\"330\" class=\"alignnone size-full wp-image-82145\" \/><\/a><\/p>\n<h2>Hit count for breakpoints<\/h2>\n<p>Line breakpoints support not only condition expressions but hit counts as well. When you specify a hit count, the PowerShell debugger notes the number of times that the breakpoint has been encountered and only breaks into the debugger after the specified hit count has been reached.<\/p>\n<p>Let\u2019s set a line breakpoint with a hit count. First, remove all previous breakpoints in DebugTest.ps1 by using the <strong>Remove All Breakpoints<\/strong> button as highlighted in the following screenshot:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/14-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/14-HSG020617.png\" alt=\"Remove All Breakpoints button\" width=\"495\" height=\"78\" class=\"alignnone size-full wp-image-82155\" \/><\/a><\/p>\n<p>Now set a line breakpoint (F9) on the line: $i = $i + 1. Right-click the Red breakpoint glyph, and select <strong>Edit Breakpoint\u2026<\/strong>. Then, click the dropdown, and select <strong>Hit Count<\/strong>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/15-HSG020617.png\" alt=\"Selecting Edit Breakpoint\" width=\"519\" height=\"66\" class=\"alignnone size-full wp-image-82165\" \/><\/a><\/p>\n<p>This UI allows you to set both <strong>Expression<\/strong> and <strong>Hit Count<\/strong> to have a conditional breakpoint that obeys the specified hit count. Let\u2019s set the hit count to 25. Press Enter to complete setting the hit count.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16-HSG020617.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/16-HSG020617.png\" alt=\"Setting Hit Count to 25\" width=\"376\" height=\"93\" class=\"alignnone size-full wp-image-82175\" \/><\/a><\/p>\n<p>Press F5 to start debugging, and you will see the debugger stop when $i is 25. After you press F5 again to continue execution, the breakpoint is not hit again.<\/p>\n<p>In this blog post, we looked at the debugging features of Visual Studio Code and the PowerShell extension.\u00a0 All debugging examples in this post used a project that had the debugger \u201cpreconfigured\u201d. In Part 2 of this series, we will look at how to configure the debugger to launch and debug your scripts.<\/p>\n<p>I think you\u2019ll find the PowerShell debugging experience in Visual Studio Code to be quite productive.\u00a0 Of course, if you do find a bug, please be sure to submit an issue at <a target=\"_blank\" href=\"https:\/\/github.com\/PowerShell\/vscode-powershell\/issues\">https:\/\/github.com\/PowerShell\/vscode-powershell\/issues<\/a> so that we can continue to improve the debug experience for everyone.<\/p>\n<p><strong>\nKeith Hill<\/strong>\nSoftware Engineer\nPowerShell MVP<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Here&#8217;s a look at the\u00a0many features of the PowerShell debugger for Visual Studio Code. In previous blog posts, we covered how to get started with PowerShell development in Visual Studio Code and the editing features of Visual Studio Code and the PowerShell extension.\u00a0 If you don\u2019t already have Visual Studio Code configured with the [&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":[568],"tags":[499,153,701],"class_list":["post-82016","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hey-scripting-guy","tag-guestblogger","tag-keith-hill","tag-visual-studio-code"],"acf":[],"blog_post_summary":"<p>Summary: Here&#8217;s a look at the\u00a0many features of the PowerShell debugger for Visual Studio Code. In previous blog posts, we covered how to get started with PowerShell development in Visual Studio Code and the editing features of Visual Studio Code and the PowerShell extension.\u00a0 If you don\u2019t already have Visual Studio Code configured with the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/82016","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=82016"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/82016\/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=82016"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=82016"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=82016"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}