about_Debuggers

簡短描述

描述 PowerShell 調試程式。

詳細描述

偵錯是在腳本執行時檢查腳本的程式,以識別並更正腳本指示中的錯誤。 PowerShell 調試程式可協助您檢查和識別腳本、函式、命令、PowerShell Desired 狀態設定 (DSC) 組態或表達式中的錯誤和效率不足。

從 PowerShell 5.0 開始,PowerShell 調試程式已更新為偵錯遠端電腦上的控制台或 Windows PowerShell 整合式腳本環境 (ISE) 中執行的腳本、函式、命令、組態或表達式。

注意

Windows PowerShell ISE 僅支援 Windows PowerShell。 針對 PowerShell 6 和更新版本,您必須搭配 PowerShell 的擴充功能使用 Visual Studio Code。 如需詳細資訊,請參閱 使用Visual Studio Code進行偵錯。

調試程式 Cmdlet

PowerShell 調試程式包含下列一組 Cmdlet:

  • Set-PSBreakpoint:在行、變數和命令上設定斷點。
  • Get-PSBreakpoint:取得目前會話中的斷點。
  • Disable-PSBreakpoint:關閉目前工作階段中的斷點。
  • Enable-PSBreakpoint:重新啟用目前會話中的斷點。
  • Remove-PSBreakpoint:從目前的工作階段刪除斷點。
  • Get-PSCallStack:顯示目前的呼叫堆疊。

啟動和停止調試程式

若要啟動調試程式,請設定一或多個斷點,然後執行您要偵錯的腳本、命令或函式。

當您到達斷點時,執行會停止,並將控制權移交給調試程式。

若要停止調試程式,請執行腳本、命令或函式,直到完成為止。 或者,輸入 stopt

調試程式命令

當您在 PowerShell 控制台中使用調試程式時,請使用下列命令來控制執行。 在 Windows PowerShell ISE 中,使用 [偵錯] 功能表上的命令。

注意

如需如何在其他主應用程式中使用調試程式的詳細資訊,請參閱主應用程式檔。

  • sStepInto:執行下一個語句,然後停止。

  • vStepOver:執行下一個語句,但會略過函式和調用。 會執行略過的語句,但不會逐步執行。

  • Ctrl+Break:(在 ISE 中全部中斷 中斷為 PowerShell 控制台或 Windows PowerShell ISE 內執行中的腳本。 請注意,Windows PowerShell 2.0、3.0 和 4.0 中的 Ctrl+中斷會關閉程式。 中斷全部適用於本機和遠端以互動方式執行的腳本。

  • oStepOut:逐步離開目前的函式;如果巢狀,則向上一個層級。 如果位於主體中,它會繼續結束或下一個斷點。 會執行略過的語句,但不會逐步執行。

  • cContinue:繼續執行,直到腳本完成或到達下一個斷點為止。 會執行略過的語句,但不會逐步執行。

  • lList:顯示正在執行的腳本部分。 根據預設,它會顯示目前的行、5 個前幾行和 10 個後續行。 若要繼續列出腳本,請按 ENTER 鍵。

  • l <m>List:顯示從 所 <m>指定的行號開始的 16 行腳本。

  • l <m> <n>List:顯示 <n> 腳本行,開頭為 所 <m>指定的行號。

  • q、 、 StopExit停止執行文稿,並結束除錯程式。 如果您要藉由執行 Debug-Job Cmdlet 來偵錯作業, Exit 命令會中斷調試程式,並允許作業繼續執行。

  • kGet-PsCallStack:顯示目前的呼叫堆疊。

  • <Enter>:如果Step為 (s)、(vStepOverListl),則重複最後一個命令。 否則,代表送出動作。

  • ?h:顯示調試程式命令說明。

若要結束調試程式,您可以使用 Stopq)。

從 PowerShell 5.0 開始,您可以執行 Exit 命令來結束您執行 Debug-JobDebug-Runspace所啟動的巢狀偵錯會話。

使用這些調試程式命令,您可以執行腳本、停止關注點、檢查變數的值和系統的狀態,並繼續執行腳本,直到您發現問題為止。

注意

如果您使用重新導向運算元逐步執行 語句,例如 >,PowerShell 調試程式會逐步執行腳本中所有剩餘語句。

顯示文稿變數的值

當您在除錯程式中時,您也可以輸入命令、顯示變數的值、使用 Cmdlet,以及在命令行執行腳本。 您可以在正在偵錯的文稿中顯示所有變數的目前值,但下列自動變數除外:

$_
$Args
$Input
$MyInvocation
$PSBoundParameters

當您顯示任何這些變數的值時,您會取得調試程式所使用之內部管線的變數值,而不是腳本中的變數值。

若要針對要偵錯的腳本顯示這些變數的值,請將幾行新增至您的腳本,將這些值儲存至新的變數。 在這些新行之後設定斷點。 然後,您可以顯示新變數的值。

例如,

$scriptArgs = $Args
$scriptname = $MyInvocation.PSCommandPath

調試程序環境

當您到達斷點時,請輸入調試程序環境。 命令提示字元會變更,使其開頭為 “[DBG]:”。 此外,在某些主機應用程式中,例如 PowerShell 控制台,會開啟巢狀提示以進行偵錯。 您可以藉由在命令提示字元中出現的重複大於字元 (ASCII 62) 來偵測巢狀提示。

如需自定義提示的詳細資訊,請參閱 about_Prompts

您可以使用自動變數來尋找巢狀層級 $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-Variable Cmdlet 的 Get-Alias Scope 參數。

例如,下列命令會取得本機 (script) 範圍中的變數:

Get-Variable -scope 0

這是只查看您在腳本中定義的變數,以及在偵錯時定義變數的實用方式。

在命令行進行偵錯

當您設定變數斷點或命令斷點時,只能在腳本檔案中設定斷點。 不過,根據預設,斷點會在目前會話中執行的任何項目上設定。

例如,如果您在變數上 $name 設定斷點,調試程式會在執行的任何 $name 腳本、命令、函式、腳本 Cmdlet 或表示式中的任何變數上中斷,直到您停用或移除斷點為止。

這可讓您在更逼真的內容中偵錯腳本,這些腳本可能會受到會話和使用者配置檔中的函式、變數和其他腳本的影響。

行斷點專屬於腳本檔案,因此只會在腳本檔案中設定。

偵錯函式

當您在具有 beginprocessend 區段的函式上設定斷點時,調試程式會在每個區段的第一行中斷。

例如:

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>

偵錯遠端文本

您可以執行 Enter-PSSession 來啟動互動式遠端 PowerShell 工作階段,您可以在其中設定斷點,並在遠端電腦上偵錯腳本檔案和命令。 Enter-PSSession 可讓您重新連接在遠端電腦上執行腳本或命令的已中斷聯機會話。 如果執行中的文稿叫用斷點,您的用戶端會話會自動啟動調試程式。 如果執行文本的已中斷聯機會話已叫用斷點,當您重新連線到會話時, 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>

範例

此測試腳本會偵測 PowerShell 版本,並顯示適當的版本訊息。 它包含函式、函數調用和變數。

下列命令會顯示測試文稿檔案的內容:

PS C:\PS-test>  Get-Content test.ps1

function psversion {
  "PowerShell " + $PSVersionTable.PSVersion
  if ($PSVersionTable.PSVersion.Major -lt 7) {
    "Upgrade to PowerShell 7!"
  }
  else {
    "Have you run a background job today (start-job)?"
  }
}

$scriptName = $MyInvocation.PSCommandPath
psversion
"Done $scriptName."

若要開始,請在腳本感興趣的點設定斷點,例如行、命令、變數或函式。

從在目前目錄中Test.ps1腳本的第一行建立行斷點開始。

PS C:\ps-test> Set-PSBreakpoint -line 1 -script 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.PSCommandPath

此時, $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”。

DBG> s
test.ps1:2       "PowerShell " + $PSVersionTable.PSVersion

偵錯訊息會在函式中包含語句的預覽。 若要執行此語句,並預覽函式中的下一個 Step 語句,您可以使用 命令。 但在此情況下,請使用 StepOut 命令 (o)。 它會完成函式的執行(除非它到達斷點),並逐步執行腳本中的下一個語句。

DBG> o
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13  "Done $scriptName"

因為我們位於腳本的最後一個語句上,因此 Step、StepOut 和 Continue 命令的效果相同。 在此情況下,請使用 StepOut (o)。

Done C:\ps-test\test.ps1
PS C:\ps-test>

StepOut 命令會執行最後一個命令。 標準命令提示字元表示調試程式已結束,並將控制權傳回給命令處理器。

現在,請再次執行調試程式。 首先,若要刪除目前的斷點,請使用 Get-PsBreakpointRemove-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.PSCommandPath
DBG>

顯示變數的 $scriptName 目前值,也就是 $null

DBG> $scriptName
DBG>

Step使用命令 (s) 來執行填入變數的語句。 然後,顯示變數的新值 $scriptName

DBG> $scriptName
C:\ps-test\test.ps1

使用步驟命令 (s) 預覽文稿中的下一個語句。

DBG> s
test.ps1:12  psversion

下一個語句是對函式的 psversion 呼叫。 若要略過函式,但仍執行函式,請使用 StepOver 命令 (v)。 如果您在使用 StepOver時已經在 函式中,則它無效。 函式呼叫隨即顯示,但不會執行。

DBG> v
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13  "Done $scriptName"

命令會執行 函 StepOver 式,並預覽腳本中的下一個語句,這會列印最後一行。

Stop使用命令 (t) 結束調試程式。 命令提示字元會還原為標準命令提示字元。

C:\ps-test>

若要刪除斷點,請使用 Get-PsBreakpointRemove-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>

現在,使用動作建立新的命令斷點。 下列命令會設定命令斷點,其動作會在呼叫 函式時記錄變數的值 $scriptNamebreak由於 關鍵詞未用於動作中,因此不會停止執行。 反引號 (`) 是行接續字元。

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=[]

此範例只示範幾個使用PowerShell調試程式的方法。

PowerShell 中的其他偵錯功能

除了 PowerShell 調試程式之外,PowerShell 還包含數個可用來偵錯腳本和函式的其他功能。

  • Cmdlet Set-PSDebug 提供非常基本的腳本偵錯功能,包括逐步執行和追蹤。

  • Set-StrictMode使用 Cmdlet 來偵測未初始化變數的參考、參考物件不存在的屬性,以及函式語法無效。

  • 將診斷語句新增至腳本,例如顯示變數值的語句、從命令行讀取輸入的語句,或報告目前指令的語句。 使用包含此工作的 Write 動詞指令的 Cmdlet,例如 Write-HostWrite-DebugWrite-WarningWrite-Verbose

另請參閱