<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://powershell.com/cs/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tags 'PowerShell ISE' and 'Debugging'</title><link>http://powershell.com/cs/search/SearchResults.aspx?q=app:weblogs&amp;tag=PowerShell+ISE,Debugging&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'PowerShell ISE' and 'Debugging'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 (Build: 30929.2835)</generator><item><title>Advanced Debugging in PowerShell</title><link>http://powershell.com/cs/blogs/windows-powershell-team/archive/2009/07/13/advanced-debugging-in-powershell.aspx</link><pubDate>Mon, 13 Jul 2009 05:00:00 GMT</pubDate><guid isPermaLink="false">f421715f-7aba-45f0-8a8d-44de5318a3a7:2874</guid><dc:creator>Anonymous</dc:creator><description>&lt;p&gt;Here is a collection of tips and tricks to debug PowerShell&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read Up&lt;br /&gt;&lt;/strong&gt;There is a 7-part series of “&lt;a href="http://www.bing.com/search?q=site%3Ablogs.msdn.com%2Fpowershell+%22debugging+monad+scripts%22&amp;amp;form=QBLH&amp;amp;qs=n"&gt;Debugging Monad Scripts&lt;/a&gt;” that Jon Newman wrote a few years ago that covers a lot of tips, including error handling, traps, tracing, and covers a lot of V1 stuff.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clean code&lt;br /&gt;&lt;/strong&gt;The best route, is to make sure code is clean, and common errors are caught. To do so, run&lt;br /&gt;Set-StrictMode -Version 2&lt;/p&gt;
&lt;p&gt;Note, there’s a lot of normal PowerShell (v1 and V2) that StrictMode barfs on, so its recommend to only use Set-StrictMode when trying to debug their own scripts.&lt;/p&gt;
&lt;p&gt;You can also change your error, and warning preference to make PowerShell stop at non-terminating errors or warning.&lt;br /&gt;For example, $ErrorActionPreference = &amp;#39;stop&amp;#39; or $WarningPreference = &amp;#39;stop&amp;#39;&lt;/p&gt;
&lt;p&gt;This makes sure that if any errors are raised, whether they are terminating or non-terminating, code will stop. Calling .net methods that throw exceptions are an example of a non-terminating error. In C#, they would be terminating.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terminating vs Non-terminating is discussed here &lt;a href="http://blogs.msdn.com/powershell/archive/2006/04/25/583228.aspx"&gt;http://blogs.msdn.com/powershell/archive/2006/04/25/583228.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Preference variables are covered here &lt;a href="http://blogs.msdn.com/powershell/archive/2006/04/25/583232.aspx"&gt;http://blogs.msdn.com/powershell/archive/2006/04/25/583232.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Set-PSDebug is discussed here &lt;a href="http://blogs.msdn.com/monad/archive/2005/11/09/491035.aspx"&gt;http://blogs.msdn.com/monad/archive/2005/11/09/491035.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Error information&lt;br /&gt;&lt;/strong&gt;$error holds the error information from commands. To get more details information, try&lt;br /&gt;$error | select -ExpandProperty Exception | Format-List -f *&lt;br /&gt;$error is explained here &lt;a href="https://blogs.msdn.com/powershell/archive/2006/04/25/583229.aspx"&gt;https://blogs.msdn.com/powershell/archive/2006/04/25/583229.aspx&lt;/a&gt;&lt;br /&gt;A better Resolve-Error function from Jeffery can be found here &lt;a href="http://blogs.msdn.com/powershell/archive/2006/12/07/resolve-error.aspx"&gt;http://blogs.msdn.com/powershell/archive/2006/12/07/resolve-error.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;$LASTEXITCODE tells you if a native command completed successfully or not. For example “ping example.com” gives $LASTEXITCODE of 1&lt;/p&gt;
&lt;p&gt;$? Tells you if the last command had any error in it. This includes if you tried to execute a command that does not exist. Pping will not set $LASTEXITCODE, but it will set $? To False&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Trapping and Catching errors&lt;br /&gt;&lt;/strong&gt;Try/catch and trap can be used to process errors&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;See more information here - &lt;a href="http://blogs.msdn.com/powershell/archive/2009/06/17/traps-vs-try-catch.aspx"&gt;http://blogs.msdn.com/powershell/archive/2009/06/17/traps-vs-try-catch.aspx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;On traps, you can see more here &lt;a href="http://blogs.msdn.com/powershell/archive/2006/04/25/583234.aspx"&gt;http://blogs.msdn.com/powershell/archive/2006/04/25/583234.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tracing&lt;br /&gt;&lt;/strong&gt;Write-Debug will write messages to the screen. You need to set, $DebugPreference = &amp;quot;continue&amp;quot;, so they actually appear. Setting $DebugPreference and $VerbosePreference can sometimes give you clues on what other commands are doing.&lt;br /&gt;Write-Host is a more normal/boring way of getting output. Out-Host is sometimes better because it preserves format and output&lt;/p&gt;
&lt;p&gt;Write-Output is usually a better alternative... Write-Host can’t be captured into log files.&lt;/p&gt;
&lt;p&gt;More info on Write-Host and Write-Output is here &lt;a href="http://blogs.msdn.com/monad/archive/2005/11/09/490625.aspx"&gt;http://blogs.msdn.com/monad/archive/2005/11/09/490625.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use the ISE Debugger&lt;br /&gt;&lt;/strong&gt;The ISE comes with a debugger that helps you to see the callstack, set and hit breakpoints, step over, into and out of your code. Find more information here - &lt;a href="http://blogs.msdn.com/powershell/archive/2009/01/19/debugging-powershell-script-using-the-ise-editor.aspx"&gt;http://blogs.msdn.com/powershell/archive/2009/01/19/debugging-powershell-script-using-the-ise-editor.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use the Console Debugger&lt;br /&gt;&lt;/strong&gt;PowerShell.exe also comes with a&amp;nbsp; debugger. It’s not as easy to use as the ISE Debugger, but it can stop at all breakpoints set using Set-PSBreakpoint. It can step-over, step-into, and step-out of code. It can even display lines from the current script.&lt;br /&gt;More information is available in about_debuggers &lt;a href="http://technet.microsoft.com/en-us/library/dd347652.aspx"&gt;http://technet.microsoft.com/en-us/library/dd347652.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finding out where you are&lt;br /&gt;&lt;/strong&gt;To find out where you are in the code, you can use “Set-PSDebug -Trace 2” this is especially useful if you get into an infinite loop, or if have little or no output from your scripts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advanced Breakpoints&lt;br /&gt;&lt;/strong&gt;Set-PSBreakpoint can do more than just line breakpoints. You can use Set-PSBreakpoint to break whenever a variable is set (-Variable) or when a command is ran (-Command)&lt;/p&gt;
&lt;p&gt;Set-PSBreakpoint –Command Out-Default is an interesting trick from James Brundage, where you can break anytime output is about to be displayed&lt;/p&gt;
&lt;p&gt;If you only want to know when something is hit, you can do&lt;br /&gt;Set-PSBreakpoint -Command dir -Action {write-host &amp;quot;hit dir&amp;quot;}&lt;/p&gt;
&lt;p&gt;If you want a conditional breakpoint, you can do something like,&lt;br /&gt;Set-PSBreakpoint -Line 10 -Script MyScript.ps1 -Action {if ($ctr -eq 0) { break }}&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debugging Modules&lt;br /&gt;&lt;/strong&gt;If you have a module, you can place breakpoints into them using the ISE. Command breakpoints can be set on private functions and variables. If you loaded a module, and you wanted to ‘peek inside’ it, you can use the call operator&lt;br /&gt;$m = Get-Module test&lt;br /&gt;&amp;amp; $m {$privateVariableValue}&lt;br /&gt;This lets you modify the module, even after you have loaded it&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debugging Jobs&lt;br /&gt;&lt;/strong&gt;Jobs are commands that run in the background in PowerShell. They have their own errors and output and you don’t get access to them directly.&lt;/p&gt;
&lt;p&gt;For example, Start-Job -ScriptBlock {1;throw &amp;quot;SomeError&amp;quot;; 2}&lt;/p&gt;
&lt;p&gt;You can see the status of the job using Get-Job &lt;br /&gt;Id&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; State&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HasMoreData&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Location&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Command&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;--&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -----&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -----------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; --------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -------&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Job1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Failed&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; True&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; localhost&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1;throw &amp;quot;SomeError&amp;quot;; 2&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;To get the errors and output from the job, use &amp;quot;(Get-Job 1).ChildJobs[0].JobStateInfo.Reason&amp;quot; or&amp;nbsp; “Receive-Job 1 –Keep”&lt;br /&gt;It will have the error and you can investigate that.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debugging Events&lt;br /&gt;&lt;/strong&gt;Debugging eventing is kind of like a mix of debugging jobs and modules and more&lt;br /&gt;Tracing works with Write-Host but not with Write-Object in events.&lt;/p&gt;
&lt;p&gt;$fsw = New-Object io.filesystemwatcher $env:tmp&lt;br /&gt;Register-ObjectEvent -InputObject $fsw -EventName Disposed -Action {write-host hi}&lt;br /&gt;$fsw.Dispose()&lt;/p&gt;
&lt;p&gt;The above will write Write-Host. Also useful in debugging eventing is using Out-GridView, in particular, “dir variable:\ | Out-GridView” gives a quick view of the special variables set in events&lt;/p&gt;
&lt;p&gt;You can get access to the related jobs, using Get-EventSubscriber | %{Get-Job -Name $_.SourceIdentifier}&lt;/p&gt;
&lt;p&gt;From the eventing jobs, you can get access to the using (Get-Job).Module&lt;br /&gt;For example, you can run, &lt;br /&gt;&amp;amp; (Get-Job).Module {$event, $eventSubscriber, $eventArgs}&lt;br /&gt;which lets your work in the event’s scope even after it has completed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debugging Remoting&lt;br /&gt;&lt;/strong&gt;For connection issues, see get-help about_remote_troubleshooting&lt;/p&gt;
&lt;p&gt;For debugging, instead on Invoke-Command, it might be better to use Enter-PSSession, so that you can have a shell on the remote machine to try things out&lt;/p&gt;
&lt;p&gt;Not all error information propagates back from remote invocations. For example,&lt;br /&gt;Invoke-Command my-server {ping example.com}&lt;br /&gt;$? And $LASTEXITCODE are not set&lt;/p&gt;
&lt;p&gt;To get $LASTEXITCODE, you should either do&lt;br /&gt;Invoke-Command localhost {ping example.com; $LASTEXITCODE}&lt;/p&gt;
&lt;p&gt;Or even better, create a persistent session&lt;br /&gt;$session = New-PSSession localhost&lt;br /&gt;Invoke-Command $session {ping example.com}&lt;br /&gt;Invoke-Command $session {$LASTEXITCODE}&lt;/p&gt;
&lt;p&gt;To do debugging using tracing, remember that you need to set the VerbosePreference, DebugPreference etc in the remote session&lt;br /&gt;Invoke-Command $session {$VerbosePreference = &amp;#39;continue&amp;#39;}&lt;br /&gt;Invoke-Command $session {Write-Verbose hi}&lt;/p&gt;
&lt;p&gt;Share your skills bug hunters, PowerShell still doesn&amp;#39;t&amp;nbsp;have a Fix-Script cmdlet.&lt;/p&gt;
&lt;p&gt;Hope this helps,&lt;br /&gt;Ibrahim Abdul Rahim [MSFT]&lt;br /&gt;This posting is provided “AS IS” with no warranties.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9832442" width="1" height="1" alt="" /&gt;</description></item></channel></rss>