{"id":259,"date":"2014-12-02T00:01:00","date_gmt":"2014-12-02T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/12\/02\/troubleshoot-by-using-set-psdebug\/"},"modified":"2022-06-22T10:12:26","modified_gmt":"2022-06-22T17:12:26","slug":"troubleshoot-by-using-set-psdebug","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/troubleshoot-by-using-set-psdebug\/","title":{"rendered":"Troubleshoot by Using Set-PSDebug"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Boe Prox uses the <\/span><b style=\"font-size:12px\">Set-PSDebug<\/b><span style=\"font-size:12px\"> cmdlet to assist in troubleshooting.<\/span><\/p>\n<p>Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the second part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes:<\/p>\n<ol>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/scripting\/provide-support-by-using-verbose-and-debug-streams\/\" target=\"_blank\" rel=\"noopener\">Provide Support by Using Verbose and Debug Streams<\/a><\/li>\n<li>Troubleshoot by Using Set-PSDebug (this post)<\/li>\n<li>Enforce Better Script Practices by Using Set-StrictMode<\/li>\n<li>Trace Your Commands by Using Trace-Command<\/li>\n<li>Use the PowerShell Debugger<\/li>\n<\/ol>\n<p>Today I am going to talk about using the <strong>Set-PSDebug<\/strong> cmdlet to assist in troubleshooting a script or function. This cmdlet provides some basic debugging capabilities and allows you to set up trace levels, depending on how you want to view the execution of a script or function. This is nice when you do not want to put together a lot of debug lines in your code. Besides that, you can track whether you are correctly assigning values to variables by using <strong>StrictMode<\/strong>.<\/p>\n<p>First let\u2019s take a look at the parameters that are available with <strong>Set-PSDebug<\/strong> and see what we can work with:<\/p>\n<p style=\"margin-left:30px\">\n  Get-Help Set-PSDebug\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug1.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>We have two parameter sets, one that supports turning off the debugging and another that allows us to turn on Strict mode, set a trace level, and the option to step through each line of the statement in the code.<\/p>\n<p>Turning on Strict mode allows us to ensure that we are defining variables in our code. For a quick example, we can run the following code:<\/p>\n<p style=\"margin-left:30px\">\n  1..10 | ForEach {\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 $i++\n<\/p>\n<p style=\"margin-left:30px\">\n  }\n<\/p>\n<p style=\"margin-left:30px\">\n  $i\n<\/p>\n<p>In this case (and assuming you have only run it once), the value of <strong>$i<\/strong> would be 10. The issue here is that we never actually defined the variable up front. Now let\u2019s set up Strict mode by using <strong>Set-PSDebug<\/strong> and try this again to see what happens.<\/p>\n<p style=\"margin-left:30px\">\n  Remove-Variable i\n<\/p>\n<p style=\"margin-left:30px\">\n  Set-PSDebug -Strict\n<\/p>\n<p style=\"margin-left:30px\">\n  1..10 | ForEach {\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 $i++\n<\/p>\n<p style=\"margin-left:30px\">\n  }\n<\/p>\n<p style=\"margin-left:30px\">\n  $i\n<\/p>\n<p>The variable <strong>$i<\/strong> cannot be retrieved because it has not been set.<\/p>\n<p style=\"margin-left:30px\">\n  At line:6 char:1\n<\/p>\n<p style=\"margin-left:30px\">\n  + $i\n<\/p>\n<p style=\"margin-left:30px\">\n  + ~~\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 + CategoryInfo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : InvalidOperation: (i:String) [], RuntimeExceptio\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0 n\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 + FullyQualifiedErrorId : VariableIsUndefined\n<\/p>\n<p>I removed the variable after my last example to show that if you attempt to increment the variable before assigning it, it will throw an error message (in this case, up to 10) stating that the variable has not yet been defined. This is pretty useful if you want to make sure that you have defined all of your variables in your script or function.<\/p>\n<p>I do not want to keep Strict mode enabled, so I will turn it off:<\/p>\n<p style=\"margin-left:30px\">\n  Set-PSDebug \u2013Off\n<\/p>\n<p>This not only turns off the Strict mode, but it will also turn off the other enabled properties, such as the trace level and stepping through each statement.<\/p>\n<p>That was pretty cool. But now let\u2019s dive into my favorite part about using <strong>Set-PSDebug<\/strong>: trace levels! This is where we can really see what is happening during the execution of the code. With <strong>Trace<\/strong>, we have the following options:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"31\" valign=\"top\">\n<p>\n          \u00a00\n        <\/p>\n<\/td>\n<td width=\"607\" valign=\"top\">\n<p>\n          \u00a0Turn off script tracing.\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"31\" valign=\"top\">\n<p>\n          \u00a01\n        <\/p>\n<\/td>\n<td width=\"607\" valign=\"top\">\n<p>\n          \u00a0Traces each line of code that is being executed. Non-executed lines are not displayed.\n        <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"31\" valign=\"top\">\n<p>\n          \u00a02\n        <\/p>\n<\/td>\n<td width=\"607\" valign=\"top\">\n<p>\n          \u00a0Traces each line of code that is being executed. Non-executed lines are not displayed. <br \/>\u00a0Displays variable assignments and calls to other functions and script blocks.\n        <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-size:12px\">We already can tell that setting the trace level to 0 turns it off, so there really is no need to demo that piece. Instead, we will go into the first level, 1, and see what happens with the code when it is executed:<\/span><\/p>\n<p style=\"margin-left:30px\">\n  Set-PSDebug \u2013Trace 1\n<\/p>\n<p>Now let\u2019s run some code to see what is displayed in the console.<\/p>\n<p style=\"margin-left:30px\">\n  ## Traces\n<\/p>\n<p style=\"margin-left:30px\">\n  Function Test {\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 Param (\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [int]$Value\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 )\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 $Value++\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 Write-Output $Value\n<\/p>\n<p style=\"margin-left:30px\">\n  }\n<\/p>\n<p style=\"margin-left:30px\">\n  Set-PSDebug -Trace 1\n<\/p>\n<p>\u00a0<\/p>\n<p style=\"margin-left:30px\">\n  [int]$z=0\n<\/p>\n<p style=\"margin-left:30px\">\n  $Return = $Null\n<\/p>\n<p style=\"margin-left:30px\">\n  Get-ChildItem | Select -First 5 | ForEach {\u00a0\u00a0\u00a0\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 If ($_.name -match &#8216;^p&#8217;) {\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $File = $_\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $Return += (&#8220;{0} [{1}]`r`n&#8221; -f $File,(Test ($z++)))\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 }\n<\/p>\n<p style=\"margin-left:30px\">\n  }\n<\/p>\n<p style=\"margin-left:30px\">\n  $Return\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug2.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>The trace level has been set to 1, meaning that only the lines that are executed will be displayed on the console. With that, we can see each iteration of <strong>Get-ChildItem<\/strong> and sometimes we have calls to the <strong>Test<\/strong> function, which increments a counter before finally displaying the files we are expecting.<\/p>\n<p>Pretty cool stuff! Now let\u2019s up the trace level to 2 and see the output!<\/p>\n<p style=\"margin-left:30px\">\n  Set-PSDebug -Trace 2\n<\/p>\n<p style=\"margin-left:30px\">\n  [int]$z=0\n<\/p>\n<p style=\"margin-left:30px\">\n  $Return = $Null\n<\/p>\n<p style=\"margin-left:30px\">\n  Get-ChildItem | Select -First 5 | ForEach {\u00a0\u00a0\u00a0\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 If ($_.name -match &#8216;^p&#8217;) {\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $File = $_\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $Return += (&#8220;{0} [{1}]`r`n&#8221; -f $File,(Test ($z++)))\n<\/p>\n<p style=\"margin-left:30px\">\n  \u00a0\u00a0\u00a0 }\n<\/p>\n<p style=\"margin-left:30px\">\n  }\n<\/p>\n<p style=\"margin-left:30px\">\n  $Return\n<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/SetPSDebug3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>We see that variable assignments are now displayed on the console along with calls to functions and script blocks. The variable assignments really help to determine if the script is functioning the way it should.<\/p>\n<p>That is all there is to using** Set-PSDebug** to help with troubleshooting scripts. Join me tomorrow when I discuss using <strong>Set-StrictMode<\/strong>.<span style=\"font-size:12px\">\u00a0<\/span><\/p>\n<p>We invite you to follow the Scripting Guy on\u00a0<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\" rel=\"noopener\">Twitter<\/a>\u00a0and\u00a0<a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\" rel=\"noopener\">Facebook<\/a>. If you have any questions, send email to the Scripting Guy at\u00a0<a href=\"mailto:scripter@microsoft.com\" target=\"_blank\" rel=\"noopener\">scripter@microsoft.com<\/a>, or post your questions on the\u00a0<a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\" rel=\"noopener\">Official Scripting Guys Forum<\/a>. Until then, see ya!<\/p>\n<p><strong>Boe Prox<\/strong>, Windows PowerShell MVP and Honorary Scripting Guy<span style=\"font-size:12px\">\u00a0<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Boe Prox uses the Set-PSDebug cmdlet to assist in troubleshooting. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the second part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes: Provide Support by [&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":[162,295,3,134,45],"class_list":["post-259","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-boe-prox","tag-debug","tag-scripting-guy","tag-troubleshooting","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Boe Prox uses the Set-PSDebug cmdlet to assist in troubleshooting. Honorary Scripting Guy and Windows PowerShell MVP, Boe Prox, here today filling in for my good friend, The Scripting Guy. This is the second part in a series of five posts about troubleshooting Windows PowerShell scripts and functions. The series includes: Provide Support by [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/259","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=259"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/259\/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=259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}