about_Debuggers
主题
about_Debuggers
简短说明
说明 Windows PowerShell 调试程序。
详细说明
调试是在脚本运行过程中对其进行检查的过程,目的是识别和更正脚本指令中的错误。Windows
PowerShell 调试程序可帮助检查和识别脚本中的错误和低效率之处。
注意:Windows PowerShell 调试程序无法远程运行。若要调试远程计算机上的脚本,请将该脚本复
制到本地计算机。
可使用 Windows PowerShell 调试程序的功能,在 Windows PowerShell 脚本、函数、命令或
表达式运行过程中对它们进行检查。Windows PowerShell 调试程序包含一组 cmdlet,可用来设置
断点、管理断点以及查看调用堆栈。
Windows PowerShell 提供了几种用于调试脚本、函数和命令的方法。
方法 1:Set-PsDebug cmdlet 提供了基本脚本调试功能,包括单步执行和跟踪。有关详细信息,
请键入:"get-help set-psdebug"。
方法 2:使用 Set-StrictMode cmdlet 来检测是否存在对未初始化变量的引用、对不存在的对象
属性的引用以及无效的函数语法。
方法 3:在脚本中添加诊断语句,如用于显示变量值的语句,用于读取命令行输入的语句,或用于报告
当前指令的语句。可出于调试目的使用包含 Write 动词的 cmdlet,如 Write-Host、Write-
Debug、Write-Warning 和 Write-Verbose。
方法 4:使用 Windows PowerShell 调试程序来调试脚本。或者,使用调试程序来调试在命令提示
符下键入的函数或脚本块。可以设置断点、单步执行脚本、检查变量的值、运行诊断和
日志记录命令并显示调用堆栈。
调试程序 Cmdlet
Windows PowerShell 调试程序包含下面一组 cmdlet:
Set-PsBreakpoint: 在行、变量和命令上设置断点。
Get-PsBreakpoint: 获取当前会话中的断点。
Disable-PsBreakpoint: 关闭当前会话中的断点。
Enable-PsBreakpoint: 重新启用当前会话中的断点。
Remove-PsBreakpoint: 删除当前会话中的断点。
Get-PsCallStack: 显示当前调用堆栈。
启动和停止调试程序
若要启动调试程序,请设置一个或多个断点。然后,运行想要调试的脚本、命令或函数。
在到达断点时,执行会停止,调试程序将接管控制。
若要停止调试程序,请运行脚本、命令或函数,直到运行完成。或者,键入“stop”或“t”。
调试程序命令
在 Windows PowerShell 控制台中使用调试程序时,可使用以下命令来控制执行。
注意:有关如何在其他主机应用程序中使用调试程序的信息,请参阅主机应用程序文档。
s, Step-into 执行下一条语句,然后停止。
v, Step-over 执行下一条语句,但跳过函数和调用。将执行被跳过的语句,
但不单步执行。
o, Step-out 移出当前函数;如果嵌套则上移一级。如果位于 main 函数体
中,则继续前进到末尾或下一个断点。将执行被跳过的语句,
但不单步执行。
c, Continue 继续运行,直到脚本完成或到达下一个断点。将执行被跳过的语
句,但不单步执行。
l, List 显示正在执行的脚本部分。默认情况下,它将显示当前行、前面
5 行和后面 10 行。若要继续列出脚本,请按 Enter。
l <m>, List 显示从 <m> 所指定的行号开始的 16 行脚本。
l <m> <n>, List 显示从 <m> 所指定的行号开始的 <n> 行脚本。
q, Stop 停止执行脚本并退出调试程序。
k, Get-PsCallStack 显示当前调用堆栈。
<Enter> 如果最后一个命令是 Step (s)、Step-over (v) 或 List (l),
则重复该命令。否则表示提交操作。
?, h 显示调试程序命令帮助。
若要退出调试程序,请使用 Stop (q)。
您还可以在调试程序中输入命令、显示变量的值、使用 cmdlet 和运行脚本。
通过使用这些调试程序命令,可以运行脚本、在相关点处停止、检查变量的值和
系统的状态,以及继续运行脚本直到发现问题。
调试程序环境
在到达断点时,会进入调试程序环境中。此时命令提示符变为以“[DBG]:”开头。可以自定义提示符。
另外,在某些主机应用程序如 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 的
Scope 参数。
例如,以下命令可获取本地(脚本)作用域中的变量:
get-variable -scope 0
可将该命令缩写为:
gv -s 0
在您只想查看在脚本中定义的变量以及在调试过程中定义的变量时,这是一个有用的方法。
在命令行上进行调试
在设置变量断点或命令断点时,可只在脚本文件中设置。但在默认情况下,
该断点会设置在运行于当前会话中的所有内容。
例如,如果在 $name 变量上设置一个断点,则调试程序将在任何运行的脚本、
命令、函数、脚本 cmdlet 或表达式中的任何 $name 变量处中断,直到将该
断点禁用或删除。
这可使您在更加真实的环境下对脚本进行调试,在这样的环境下,脚本可能会
受到会话中和用户配置文件中的函数、变量以及其他脚本的影响。
行断点是脚本文件所特有的,因此只能在脚本文件中设置。
调试函数
当在包含 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 调试程序。若要调试远程
计算机上的脚本,请将该脚本复制到本地计算机。
以下命令将 Test.ps1 脚本从 Server01 远程计算机复制到本地计算机:
invoke-command -computername Server01 `
{get-content c:\ps-test\test.ps1} | set-location c:\ps-test\test.ps1
示例
此测试脚本检测操作系统的版本,并显示一条与系统相关的消息。
脚本中包含一个函数、一个函数调用和一个变量。
以下命令显示测试脚本文件的内容:
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
现在启动脚本。脚本到达变量断点。默认模式为 Write,因此将恰好在更改变量值的语句之前停止执行。
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
显示 $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
另请参阅
Disable-PsBreakpoint
Get-PsBreakpoint
Remove-PsBreakpoint
Set-PsBreakpoint
Set-PsDebug
Set-Strictmode
Write-Debug
Write-Verbose
Enable-PsBreakpoint
Get-PsCallStack