主题 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