In the previous tip we have used Get-PSCallStack to determine the “nest level” of code. Let’s today take a look at how this cmdlet can help during debugging. To illustrate this, save the below code to a script file. It is important that it is in fact is a ps1 file. Execute it in the PowerShell ISE.
function test1 { test2 } function test2 { Wait-Debugger Get-Process } test1
test1 is calling test2, and inside test2, there is a call to Wait-Debugger. This cmdlet was introduced in PowerShell 5 and breaks into the debugger. If you use an older version of PowerShell, you can set a breakpoint using F9. When you run the code, the debugger stops right before Get-Process is about to execute, and the line is highlighted in yellow (if not: did you save the code to file?).
In the interactive PowerShell console, you can now enter Get-PSCallStack to find out how you ended up in the script block where you are:
[DBG]: PS C:\>> Get-PSCallStack Command Arguments Location ------- --------- -------- test2 {} a1.ps1: Line 11 test1 {} a1.ps1: Line 5 a1.ps1 {} a1.ps1: Line 14
The output indicates that you are currently inside function test2 which was called by test1 which was called by a1.ps1.
You can get even more information when you look at the hidden InvocationInfo property:
[DBG]: PS C:\>> Get-PSCallStack | Select-Object -ExpandProperty InvocationInfo MyCommand : test2 BoundParameters : {} UnboundArguments : {} ScriptLineNumber : 5 OffsetInLine : 5 HistoryId : 17 ScriptName : C:\Users\tobwe\Documents\PowerShell\a1.ps1 Line : test2 PositionMessage : In C:\Users\tobwe\Documents\PowerShell\a1.ps1:5 Line:5 + test2 + ~~~~~ PSScriptRoot : C:\Users\tobwe\Documents\PowerShell PSCommandPath : C:\Users\tobwe\Documents\PowerShell\a1.ps1 InvocationName : test2 PipelineLength : 1 PipelinePosition : 1 ExpectingInput : False CommandOrigin : Internal DisplayScriptPosition : MyCommand : test1 BoundParameters : {} UnboundArguments : {} ScriptLineNumber : 14 OffsetInLine : 1 HistoryId : 17 ScriptName : C:\Users\tobwe\Documents\PowerShell\a1.ps1 Line : test1 PositionMessage : In C:\Users\tobwe\Documents\PowerShell\a1.ps1:14 Line:1 + test1 + ~~~~~ PSScriptRoot : C:\Users\tobwe\Documents\PowerShell PSCommandPath : C:\Users\tobwe\Documents\PowerShell\a1.ps1 InvocationName : test1 PipelineLength : 1 PipelinePosition : 1 ExpectingInput : False CommandOrigin : Internal DisplayScriptPosition : MyCommand : a1.ps1 BoundParameters : {} UnboundArguments : {} ScriptLineNumber : 0 OffsetInLine : 0 HistoryId : 17 ScriptName : Line : PositionMessage : PSScriptRoot : PSCommandPath : InvocationName : C:\Users\tobwe\Documents\PowerShell\a1.ps1 PipelineLength : 2 PipelinePosition : 1 ExpectingInput : False CommandOrigin : Internal DisplayScriptPosition :
psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU – with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!