about_Debuggers
应用到: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0
在此处插入介绍。
about_Debuggers
介绍 Windows PowerShell® 调试程序。
调试是在脚本运行时对它进行检查以识别和更正脚本说明中的错误的过程。Windows PowerShell 调试程序旨在帮助你检查并确定脚本、函数、命令、Windows PowerShell 工作流或表达式中的错误和低效。
在 Windows PowerShell 4.0 中,Windows PowerShell 调试程序已更新为调试在远程计算机上的 Windows PowerShell 控制台(而不是 ISE)中运行的脚本、函数、工作流、命令或表达式。可运行 Enter-PSSession 来启动交互式远程 PowerShell 会话,你可以在该会话中设置断点,并调试远程计算机上的脚本文件和命令。Enter-PSSession 功能已更新,可让你重新连接到一个断开连接的会话并进入该会话,该会话正在远程计算机上运行一个脚本或命令。如果正在运行的脚本命中断点,客户端会话会自动启动调试程序。如果正在运行脚本的断开连接的会话已命中断点,并在断点处停止,则 Enter-PSSession 将在重新连接到会话后自动启动命令行调试程序。
Windows PowerShell 4.0 调试程序还可用于在 Windows PowerShell 控制台或 Windows PowerShell ISE 中调试 Windows PowerShell 工作流。
你可以使用 Windows PowerShell 调试程序的功能检查 Windows PowerShell 脚本、函数、命令、工作流或表达式(在其运行期间)。Windows PowerShell 调试程序包括一组 cmdlet,可供你设置断点、管理断点和查看调用堆栈。
Windows PowerShell 调试程序包括以下一组 cmdlet:
Set-PsBreakpoint: Sets breakpoints on lines, variables, and
commands.
Get-PsBreakpoint: Gets breakpoints in the current session.
Disable-PsBreakpoint: Turns off breakpoints in the current session.
Enable-PsBreakpoint: Re-enables breakpoints in the current session.
Remove-PsBreakpoint: Deletes breakpoints from the current session.
Get-PsCallStack: Displays the current call stack.
若要启动调试程序,请设置一个或多个断点。然后,运行想要调试的脚本、命令或函数。
到达断点时,执行将停止,转由调试程序进行控制。
若要停止调试程序,请运行脚本、命令或函数,直到完成为止。或者,键入“stop”或“t”。
在 Windows PowerShell 控制台中使用调试程序时,请使用以下命令来控制执行。在 Windows PowerShell ISE 中,使用“调试”菜单上的命令。
注意:有关如何在其他主机应用程序中使用调试程序的信息,请参阅主机应用程序文档。
s, Step-into Executes the next statement and then stops.
v, Step-over Executes the next statement, but skips functions
and invocations. The skipped statements are
executed, but not stepped through.
o, Step-out Steps out of the current function; up one level
if nested. If in the main body, it continues to
the end or the next breakpoint. The skipped
statements are executed, but not stepped through.
c, Continue Continues to run until the script is complete or
until the next breakpoint is reached. The skipped
statements are executed, but not stepped through.
l, List Displays the part of the script that is executing.
By default, it displays the current line, five
previous lines, and 10 subsequent lines. To continue
listing the script, press ENTER.
l <m>, List Displays 16 lines of the script beginning with the
line number specified by <m>.
l <m> <n>, List Displays <n> lines of the script, beginning with the
line number specified by <m>.
q, Stop Stops executing the script, and exits the debugger.
k, Get-PsCallStack Displays the current call stack.
<Enter> Repeats the last command if it was Step (s),
Step-over (v), or List (l). Otherwise, represents a
submit action.
?, h Displays the debugger command Help.
To exit the debugger, use Stop (q).
通过使用这些调试程序命令,你可以运行脚本、在关注点处停止、检查变量的值和系统的状态,并继续运行脚本,直到识别问题。
注意:
如果使用重定向运算符(如“>”)单步执行一条语句,则 Windows PowerShell 调试程序将逐过程执行脚本中的所有剩余语句。
在调试程序中,你还可以输入命令、显示变量的值、使用 cmdlet,并在命令行运行脚本。
可以显示正在调试的脚本中所有变量的当前值,以下自动变量除外:
$_
$Args
$Input
$MyInvocation
$PSBoundParameters
如果尝试显示任何这些变量的值,则获取的是调试程序在内部管道中使用的该变量的值,而不是该变量在脚本中的值。
若要显示正在调试的脚本中这些变量的值,请在脚本中将自动变量的值赋给新变量。然后,你可以显示新变量的值。
例如,
$scriptArgs = $Args
$scriptArgs
在本主题的示例中,按以下方法为 $MyInvocation 变量重新赋值:
$scriptname = $MyInvocation.MyCommand.Path
到达断点时即已进入调试程序环境。命令提示符更改,因此它以“[DBG]:”开头。如果正在调试工作流,则提示符为“[WFDBG]”。你可以自定义提示符。
此外,在某些主机应用程序中(如 Windows PowerShell 控制台中,但不能在 Windows PowerShell 集成脚本环境 [ISE] 中),嵌套的提示符打开以进行调试。可通过重复在命令提示符处出现的大于字符 (ASCII 62) 来检测嵌套提示符。
例如,以下是 Windows PowerShell 控制台中的默认调试提示符:
[DBG]: PS (get-location)>>>
可通过使用 $NestedPromptLevel 自动变量查明嵌套级别。
此外,自动变量 $PSDebugContext 是在本地作用域中定义的。可通过确定 $PsDebugContext 变量是否存在来确定你是否在调试程序中。
例如:
if ($psdebugcontext) {"Debugging"} else {"Not Debugging"}
可在调试过程中使用 $PSDebugContext 变量的值。
[DBG]: PS>>> $psdebugcontext.invocationinfo
Name CommandLineParameters UnboundArguments Location
---- --------------------- ---------------- --------
= {} {} C:\ps-test\vote.ps1 (1)
进入调试程序不会更改正在操作的作用域,但在到达脚本中的断点时,将会进入脚本作用域。脚本作用域是之前运行调试程序的作用域的子级。
若要查找在脚本作用域中定义的变量和别名,请使用作用域参数 Get-Alias 或 Get-Variable cmdlet。
例如,下面的命令获取本地(脚本)作用域中的变量:
get-variable -scope 0
可将此命令缩写为:
gv -s 0
此方法对于仅查看在脚本中定义的变量和在调试过程中定义的变量非常有用。
设置变量断点或命令断点时,可以仅在脚本文件中设置断点。但是,在默认情况下,断点可设置在当前会话中运行的任何内容上。
例如,如果你在 $name 变量上设置了断点,则在运行任何脚本、命令、函数、脚本 cmdlet 或表达式时,调试程序都将在其中的 name 处中断,直到你禁用或删除该断点。
这可让你在更加真实的上下文中调试脚本,在该上下文中脚本可能受到会话和用户配置文件中的函数、变量和其他脚本的影响。
行断点是特定于脚本文件的,所以仅可在脚本文件中设置行断点。
Windows PowerShell 4.0 调试程序可用于在 Windows PowerShell 控制台或 Windows PowerShell ISE 中调试 Windows PowerShell 工作流。使用 Windows PowerShell 调试程序调试工作流有一些限制。
-- You can view workflow variables while you are in the debugger, but
setting workflow variables from within the debugger is not supported.
-- Tab completion when stopped in the workflow debugger is not
available.
-- Workflow debugging works only with synchronous running of workflows from
a Windows PowerShell script. You cannot debug workflows if they are
running as a job (with the –AsJob parameter).
-- Other nested debugging scenarios--such as a workflow calling another
workflow, or a workflow calling a script--are not implemented.
下面的示例演示如何调试工作流。请注意,当调试程序单步执行工作流函数时,调试程序提示符更改为 [WFDBG]。
PS C:\> Set-PSBreakpoint -Script C:\TestWFDemo1.ps1 -Line 8
ID Script Line Command Variable Action
-- ------ ---- ------- -------- ------
0 TestWFDemo1.ps1 8
PS C:\> C:\TestWFDemo1.ps1
Entering debug mode. Use h or ? for help.
Hit Line breakpoint on 'C:\TestWFDemo1.ps1:8'
At C:\TestWFDemo1.ps1:8 char:5
+ Write-Output -InputObject "Now writing output:"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[WFDBG:localhost]: PS C:\>> list
3:
4: workflow SampleWorkflowTest
5: {
6: param ($MyOutput)
7:
8:* Write-Output -InputObject "Now writing output:"
9: Write-Output -Input $MyOutput
10:
11: Write-Output -InputObject "Get PowerShell process:"
12: Get-Process -Name powershell
13:
14: Write-Output -InputObject "Workflow function complete."
15: }
16:
17: # Call workflow function
18: SampleWorkflowTest -MyOutput "Hello"
[WFDBG:localhost]: PS C:\>> $MyOutput
Hello
[WFDBG:localhost]: PS C:\>> stepOver
Now writing output:
At C:\TestWFDemo1.ps1:9 char:5
+ Write-Output -Input $MyOutput
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[WFDBG:localhost]: PS C:\>> list
4: workflow SampleWorkflowTest
5: {
6: param ($MyOutput)
7:
8: Write-Output -InputObject "Now writing output:"
9:* Write-Output -Input $MyOutput
10:
11: Write-Output -InputObject "Get PowerShell process:"
12: Get-Process -Name powershell
13:
14: Write-Output -InputObject "Workflow function complete."
15: }
16:
17: # Call workflow function
18: SampleWorkflowTest -MyOutput "Hello"
19:
[WFDBG:localhost]: PS C:\>> stepOver
Hello
At C:\TestWFDemo1.ps1:11 char:5
+ Write-Output -InputObject "Get PowerShell process:"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[WFDBG:localhost]: PS C:\>> stepOut
Get PowerShell process:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName
------- ------ ----- ----- ----- ------ -- ----------- --------------
433 35 106688 128392 726 2.67 7124 powershell localhost
499 44 134244 172096 787 2.79 7452 powershell localhost
Workflow function complete.
在包含 Begin、Process 和 End 部分的函数上设置断点时,调试程序将在每个部分的第一行中断。
例如:
function test-cmdlet
{
begin
{
write-output "Begin"
}
process
{
write-output "Process"
}
end
{
write-output "End"
}
}
C:\PS> set-psbreakpoint -command test-cmdlet
C:\PS> test-cmdlet
Begin
Entering debug mode. Use h or ? for help.
Hit Command breakpoint on 'prompt:test-cmdlet'
test-cmdlet
[DBG]: C:\PS> c
Process
Entering debug mode. Use h or ? for help.
Hit Command breakpoint on 'prompt:test-cmdlet'
test-cmdlet
[DBG]: C:\PS> c
End
Entering debug mode. Use h or ? for help.
Hit Command breakpoint on 'prompt:test-cmdlet'
test-cmdlet
[DBG]: C:\PS>
在 Windows PowerShell 4.0 中,可在 Windows PowerShell 4.0 控制台中的远程会话中运行 Windows PowerShell 调试程序。Enter-PSSession 功能已更新,可让你重新连接到断开连接的会话并进入该会话,该会话在远程计算机上运行,并且当前正在运行一个脚本。如果正在运行的脚本命中断点,客户端会话会自动启动调试程序。下面的示例在脚本中的第 6、11、22 和 25 行设置断点,说明了相关工作方式。请注意,在示例中,调试程序启动时有两个标识提示符:运行会话的计算机的名称和让你知道正处于调试模式中的 DBG 提示符。
Enter-Pssession -Cn localhost
[localhost]: PS C:\psscripts> Set-PSBreakpoint .\ttest19.ps1 6,11,22,25
ID Script Line Command Variable Action
-- ------ ---- ------- -------- ------
0 ttest19.ps1 6
1 ttest19.ps1 11
2 ttest19.ps1 22
3 ttest19.ps1 25
[localhost]: PS C:\psscripts> .\ttest19.ps1
Hit Line breakpoint on 'C:\psscripts\ttest19.ps1:11'
At C:\psscripts\ttest19.ps1:11 char:1
+ $winRMName = "WinRM"
+ ~
[localhost]: [DBG]: PS C:\psscripts>> list
6: 1..5 | foreach { sleep 1; Write-Output "hello2day $_" }
7: }
8:
9: $count = 10
10: $psName = "PowerShell"
11:* $winRMName = "WinRM"
12: $myVar = 102
13:
14: for ($i=0; $i -lt $count; $i++)
15: {
16: sleep 1
17: Write-Output "Loop iteration is: $i"
18: Write-Output "MyVar is $myVar"
19:
20: hello2day
21:
[localhost]: [DBG]: PS C:\psscripts>> stepover
At C:\psscripts\ttest19.ps1:12 char:1
+ $myVar = 102
+ ~
[localhost]: [DBG]: PS C:\psscripts>> quit
[localhost]: PS C:\psscripts> Exit-PSSession
PS C:\psscripts>
此测试脚本检测操作系统的版本并显示相应系统消息。这包括函数、函数调用和变量。
下面的命令显示测试脚本文件的内容:
c:>\PS-test> get-content test.ps1
function psversion {
"Windows PowerShell " + $psversiontable.psversion
if ($psversiontable.psversion.major -lt 2) {
"Upgrade to Windows PowerShell 2.0!"
}
else {
"Have you run a background job today (start-job)?"
}
}
$scriptname = $MyInvocation.MyCommand.Path
psversion
"Done $scriptname."
若要开始,请在脚本中的相关点(例如行、命令、变量或函数)处设置断点。
首先在当前目录中的 Test.ps1 脚本的第一行处创建行断点。
PS C:\ps-test> set-psbreakpoint -line 1 -script test.ps1
可将此命令缩写为:
PS C:\ps-test> spb 1 -s test.ps1
该命令返回一个行断点对象 (System.Management.Automation.LineBreakpoint)。
Column : 0
Line : 1
Action :
Enabled : True
HitCount : 0
Id : 0
Script : C:\ps-test\test.ps1
ScriptName : C:\ps-test\test.ps1
现在,启动脚本。
PS C:\ps-test> .\test.ps1
当脚本到达第一个断点时,断点消息指示调试程序处于活动状态。它介绍该断点并预览脚本的第一行,即函数声明。命令提示符也会更改,以指示调试程序具有控制权。
预览行包括脚本名称和所预览命令的行号。
Entering debug mode. Use h or ? for help.
Hit Line breakpoint on 'C:\ps-test\test.ps1:1'
test.ps1:1 function psversion {
DBG>
使用 Step 命令 (s) 执行脚本中的第一个语句并预览下一个语句。下一个语句使用 $MyInvocation 自动变量将 $ScriptName 变量的值设置为脚本文件的路径和文件名。
DBG> s
test.ps1:11 $scriptname = $MyInvocation.MyCommand.Path
此时,未填充 $ScriptName 变量,但你可以通过显示该变量的值来验证该变量值。在此例中,该值为 $null。
DBG> $scriptname
DBG>
再使用一个 Step 命令 (s) 执行当前语句并预览脚本中的下一个语句。下一个语句调用 PsVersion 函数。
DBG> s
test.ps1:12 psversion
此时,未填充 $ScriptName 变量,但可以通过显示该变量的值来验证该变量值。在此例中,该值设置为脚本路径。
DBG> $scriptname
C:\ps-test\test.ps1
再使用一个 Step 命令来执行函数调用。按 ENTER,或键入“s”以执行 Step 命令。
DBG> s
test.ps1:2 "Windows PowerShell " + $psversiontable.psversion
调试消息包含函数中语句的预览。若要执行此语句并预览函数中的下一个语句,可以使用 Step 命令。但在此例中,使用 Step-Out 命令 (o)。该命令完成函数执行(直到它到达断点为止),并转到脚本中的下一个语句。
DBG> o
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13 "Done $scriptname"
由于我们位于脚本的最后一个语句,因此 Step、Step-Out 和 Continue 命令具有同样的效果。在此例中,使用 Step-Out (o)。
Done C:\ps-test\test.ps1
PS C:\ps-test>
Step-Out 命令执行最后一个命令。标准命令提示符指示调试程序已退出,并且将控制权返回给命令处理程序。
现在,再次运行调试程序。首先,使用 Get-PsBreakpoint 和 Remove-PsBreakpoint cmdlet 删除当前断点。(如果你认为可能会重复使用断点,请使用 Disable-PsBreakpoint cmdlet 而不是 Remove-PsBreakpoint。)
PS C:\ps-test> Get-PsBreakpoint | Remove-PSBreakpoint
可将此命令缩写为:
PS C:\ps-test> gbp | rbp
或者,通过编写诸如以下形式的函数运行命令:
function delbr { gbp | rbp }
现在,在 $scriptname 变量上创建一个断点。
PS C:\ps-test> set-psbreakpoint -variable scriptname -script test.ps1
可将此命令缩写为:
PS C:\ps-test> sbp -v scriptname -s test.ps1
现在,启动脚本。该脚本到达变量断点。默认模式为写入,因此正好在更改变量值的语句之前停止执行。
PS C:\ps-test> .\test.ps1
Hit Variable breakpoint on 'C:\ps-test\test.ps1:$scriptname'
(Write access)
test.ps1:11 $scriptname = $MyInvocation.mycommand.path
DBG>
显示 $scriptname 变量的当前值,即 $null。
DBG> $scriptname
DBG>
使用 Step 命令 (s) 执行填充该变量的语句。然后,显示 $scriptname 变量的新值。
DBG> $scriptname
C:\ps-test\test.ps1
使用 Step 命令 (s) 预览脚本中的下一个语句。
DBG> s
test.ps1:12 psversion
下一个语句是对 PsVersion 函数的调用。若要跳过该函数,但仍加以执行,请使用 Step-Over 命令 (v)。如果使用 Step-Over 时已在函数中,则它不会生效。显示函数调用,但未执行。
DBG> v
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13 "Done $scriptname"
Step-Over 命令执行函数,并预览脚本中的下一个语句,该语句打印最后一行。
使用 Stop 命令 (t) 退出调试程序。命令提示符还原为标准命令提示符。
C:\ps-test>
若要删除断点,请使用 Get-PsBreakpoint 和 Remove-PsBreakpoint cmdlet。
PS C:\ps-test> Get-PsBreakpoint | Remove-PSBreakpoint
在 PsVersion 函数上创建新的命令断点。
PS C:\ps-test> Set-PsBreakpoint -command psversion -script test.ps1
可将此命令缩写为:
PS C:\ps-test> sbp -c psversion -s test.ps1
现在,运行脚本。
PS C:\ps-test> .\test.ps1
Hit Command breakpoint on 'C:\ps-test\test.ps1:psversion'
test.ps1:12 psversion
DBG>
该脚本到达函数调用处的断点。此时,尚未调用该函数。这让你有机会使用 Set-PsBreakpoint 的 Action 参数来为执行断点设置条件,或者执行准备或诊断任务,例如启动一个日志或调用一个诊断或安全脚本。
若要设置某项操作,使用 Continue 命令 (c) 退出脚本,并使用 Remove-PsBreakpoint 命令删除当前断点。(断点是只读的,因此不能将操作添加到当前断点。)
DBG> c
Windows PowerShell 2.0
Have you run a background job today (start-job)?
Done C:\ps-test\test.ps1
PS C:\ps-test> get-psbreakpoint | remove-psbreakpoint
PS C:\ps-test>
现在,创建新的命令断点以及一个操作。下面的命令设置命令断点以及操作,该操作记录调用函数时 $scriptname 变量的值。由于操作中未使用 Break 关键字,因此执行不会停止。(反撇号 (`) 为行继续符。)
PS C:\ps-test> set-psbreakpoint -command psversion -script test.ps1 `
-action { add-content "The value of `$scriptname is $scriptname." `
-path action.log}
也可以添加设置断点条件的操作。在下面的命令中,仅在执行策略设置为 RemoteSigned 时才执行命令断点,该策略是仍允许运行脚本的限制最多的策略。(反撇号 (`) 是继续符。)
PS C:\ps-test> set-psbreakpoint -script test.ps1 -command psversion `
-action { if ((get-executionpolicy) -eq "RemoteSigned") { break }}
操作中的 Break 关键字指示调试程序执行断点。也可使用 Continue 关键字指示调程序在不中断的情况下执行。由于默认关键字为 Continue,必须指定 Break 来停止执行。
现在,运行脚本。
PS C:\ps-test> .\test.ps1
Hit Command breakpoint on 'C:\ps-test\test.ps1:psversion'
test.ps1:12 psversion
由于执行策略设置为 RemoteSigned,执行将在函数调用处停止。
此时,你可能想要检查调用堆栈。使用 Get-PsCallStack cmdlet 或 Get-PsCallStack 调试程序命令 (k)。下面的命令获取当前调用堆栈。
DBG> k
2: prompt
1: .\test.ps1: $args=[]
0: prompt: $args=[]
此示例仅演示了众多 Windows PowerShell 调试程序使用方法的其中几个方法。
要获取有关调试程序 cmdlet 的详细信息,请键入以下命令:
help <cmdlet-name> -full
例如,键入:
help set-psbreakpoint -full
除了 Windows PowerShell 调试程序之外,Windows PowerShell 还包括可用于调试脚本和函数的其他几个功能。
-- Windows PowerShell Integrated Scripting Environment (ISE) includes
an interactive graphical debugger. For more information, start Windows
PowerShell ISE and press F1.
-- The Set-PSDebug cmdlet offers very basic script debugging features,
including stepping and tracing.
-- Use the Set-StrictMode cmdlet to detect references to
uninitialized variables, to references to non-existent properties
of an object, and to function syntax that is not valid.
-- Add diagnostic statements to a script, such as statements that
display the value of variables, statements that read input from
the command line, or statements that report the current
instruction. Use the cmdlets that contain the Write verb for
this task, such as Write-Host, Write-Debug, Write-Warning, and
Write-Verbose.
Disable-PsBreakpoint
Enable-PsBreakpoint
Get-PsBreakpoint
Get-PsCallStack
Remove-PsBreakpoint
Set-PsBreakpoint
Set-PsDebug
Set-Strictmode
Write-Debug
Write-Verbose