-
-
Notifications
You must be signed in to change notification settings - Fork 21
/
Test-Debugger.ps1
142 lines (109 loc) · 4.13 KB
/
Test-Debugger.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<#
.Synopsis
Tests PowerShell debugging with breakpoints.
Author: Roman Kuzmin
.Description
This scripts helps to get familiar with various breakpoints: command,
variable (reading, writing, reading and writing), and custom actions.
It is also useful for testing debuggers, e.g. Add-Debugger.ps1.
The script sets some breakpoints in itself and triggers them all during
execution. In order to set breakpoints without testing, use NoTest. In
order to remove breakpoints, use RemoveBreakpoints.
With built-in debuggers it is ready to use, e.g. with
- ConsoleHost
- VSCode PowerShell host
- Windows PowerShell ISE Host
- FarHost (in the main session)
Use it with a custom debugger, e.g. Add-Debugger.ps1, with
- Default Host (simple calls of PowerShell from .NET)
- Package Manager Host (Visual Studio NuGet console)
- FarHost
.Parameter NoTest
Tells to set breakpoints and exit without testing.
.Parameter RemoveBreakpoints
Tells to remove breakpoints set for this script.
.Example
>
# add debugger (or use the built-in and skip this)
Add-Debugger.ps1
# set and test breakpoints
Test-Debugger.ps1
.Link
https://github.com/nightroman/PowerShelf
#>
[CmdletBinding()]
param(
[switch]$NoTest
,
[switch]$RemoveBreakpoints
)
# this script path
$script = $MyInvocation.MyCommand.Definition
# get its breakpoints
$breakpoints = Get-PSBreakpoint | Where-Object { $_.Script -eq $script }
### remove breakpoints and exit
if ($RemoveBreakpoints) {
$breakpoints | Remove-PSBreakpoint
return "Removed $($breakpoints.Count) breakpoints."
}
### set breakpoints and exit
if (!$breakpoints) {
# command breakpoint, e.g. function TestFunction1
$null = Set-PSBreakpoint -Script $script -Command TestFunction1
# variable breakpoint on reading
$null = Set-PSBreakpoint -Script $script -Variable varRead -Mode Read
# variable breakpoint on writing
$null = Set-PSBreakpoint -Script $script -Variable varWrite -Mode Write
# variable breakpoint on reading and writing
$null = Set-PSBreakpoint -Script $script -Variable varReadWrite -Mode ReadWrite
# special handy breakpoint enables debugging of terminating errors
$null = Set-PSBreakpoint -Script $script -Variable StackTrace -Mode Write
# special breakpoint with action without breaking (for logging, diagnostics and etc.)
# NOTE: mind infinite recursion (stack overflow) if the action accesses the same variables
$null = Set-PSBreakpoint -Script $script -Variable 'varRead', 'varWrite', 'varReadWrite' -Mode ReadWrite -Action {
++$script:VarAccessCount
}
if ($NoTest) {
return 'Breakpoints are set, invoke the script again to test.'
}
}
### proceed with the breakpoints
# it is updated by the breakpoint action
$script:VarAccessCount = 0
# a command breakpoint is set for this function
function TestFunction1 {
TestFunction2 42 text @{data=3.14} # try to step into, over, out
'In TestFunction1'
}
# function to test stepping into from TestFunction1
function TestFunction2 { # you have stepped into TestFunction2
param($int, $text, $data)
'In TestFunction2'
}
# test a command breakpoint
TestFunction1 # in v2 it stops here, in v3 in the function
# non terminating error does not trigger debugging
Write-Error 'This is non terminating demo error.' -ErrorAction SilentlyContinue
# terminating error triggers the StackTrace breakpoint
try { Write-Error 'This is terminating demo error.' -ErrorAction Stop }
catch { $_ }
# to change the variable in a debugger, mind that in some debuggers it is the
# current scope, in others it may be the parent scope (Add-Debugger.ps1).
[int]$toWrite = 0 # change me after
if ($toWrite -le 0) {
"Nothing to write."
}
else {
"Writing..."
1..$toWrite
}
# steps in one line
if ($true) { $_ = 1 } # step through the pieces of command
$varRead = 1 # no break
$null = $varRead # break on reading
$varWrite = 2 # break on writing
$null = $varWrite # no break
$varReadWrite = 3 # break on writing
$null = $varReadWrite # break on reading
# it was updated by the breakpoint action
"Watched variables have been accessed $($script:VarAccessCount) times."