關於調試程式
簡短描述
描述 PowerShell 調試程式。
詳細描述
偵錯是在文稿執行時檢查腳本的程式,以識別並更正腳本指令中的錯誤。 PowerShell 調試程式可協助您檢查和識別腳本、函式、命令、PowerShell 工作流程、PowerShell Desired State Configuration (DSC) 組態或表達式中的錯誤和效率。
從 PowerShell 5.0 開始,PowerShell 調試程式已更新為偵錯遠端電腦上的控制台或 Windows PowerShell ISE 中執行的腳本、函式、工作流程、命令、組態或表達式。 您可以執行 Enter-PSSession
來啟動互動式遠端 PowerShell 工作階段,您可以在其中設定斷點和偵錯遠端電腦上的腳本檔案和命令。 Enter-PSSession
功能已更新,可讓您重新連線並輸入在遠端電腦上執行腳本或命令的已中斷聯機會話。 如果執行中的文稿叫用斷點,您的用戶端會話會自動啟動調試程式。 如果執行文稿的已中斷聯機會話已叫用斷點,並在斷點停止, Enter-PSSession
請在重新連線到會話之後自動啟動命令行調試程式。
PowerShell 調試程式也可以用來偵錯 PowerShell 工作流程、PowerShell 控制台或 Windows PowerShell ISE。 從 PowerShell 5.0 開始,您可以在本機或遠端對執行中的作業或進程進行偵錯。
您可以在 PowerShell 調試程式執行時,使用 PowerShell 調試程式的功能來檢查 PowerShell 腳本、函式、命令、工作流程或表達式。 PowerShell 調試程式包含一組 Cmdlet,可讓您設定斷點、管理斷點,以及檢視呼叫堆疊。
調試程式 Cmdlet
PowerShell 調試程式包含下列一組 Cmdlet:
Set-PSBreakpoint
:在行、變數和命令上設定斷點。Get-PSBreakpoint
:取得目前會話中的斷點。Disable-PSBreakpoint
:關閉目前工作階段中的斷點。Enable-PSBreakpoint
:重新啟用目前會話中的斷點。Remove-PSBreakpoint
:從目前的工作階段中刪除斷點。Get-PSCallStack
:顯示目前的呼叫堆疊。
啟動和停止偵錯工具
若要啟動調試程式,請設定一或多個斷點。 然後,執行您要偵錯的腳本、命令或函式。
當您到達斷點時,執行會停止,而控制權會開啟至調試程式。
若要停止調試程式,請執行腳本、命令或函式,直到完成為止。 或者,輸入 stop
或 t
。
調試程式命令
當您在 PowerShell 控制台中使用調試程式時,請使用下列命令來控制執行。 在 Windows PowerShell ISE 中,使用 [偵錯] 功能表上的命令。
注意:如需如何在其他主應用程式中使用調試程式的詳細資訊,請參閱主應用程式檔。
s
、StepInto
:執行下一個語句,然後停止。v
、StepOver
:執行下一個語句,但會略過函式和調用。 這會執行已跳過的陳述式,但不會逐步執行。Ctrl+Break
: (ISE 中的所有中斷) 中斷為 PowerShell 控制台內的執行中腳本,或 Windows PowerShell ISE。 請注意,Windows PowerShell 2.0、3.0 和 4.0 中的 Ctrl+Break 會關閉程式。 [全部中斷] 適用於本機和遠端以互動方式執行的腳本。o
,StepOut
:從目前的函式中跳出;如果巢狀,則向上一個層級。 如果在主本文中,它會繼續到結尾或下一個斷點。 這會執行已跳過的陳述式,但不會逐步執行。c
,Continue
:繼續執行,直到腳本完成或到達下一個斷點為止。 這會執行已跳過的陳述式,但不會逐步執行。l
,List
:顯示正在執行的腳本部分。 根據預設,它會顯示目前行、五個前幾行和10個後續行。 若要繼續列出腳本,請按 ENTER 鍵。l <m>
,List
:顯示 16 行的腳本,開頭為 所<m>
指定的行號。l <m> <n>
,List
:顯示<n>
腳本的行,開頭為 所<m>
指定的行號。q
、 、Stop
Exit
停止執行文稿,並結束除錯程式。 如果您要執行Debug-Job
Cmdlet 來偵錯作業,Exit
命令會中斷調試程式,並允許作業繼續執行。k
,Get-PsCallStack
:顯示目前的呼叫堆疊。<Enter>
:如果步驟 () 、StepOver (v) 或 List (l) ,請重複最後一個命令。 否則,表示提交動作。?
,h
:顯示調試程式命令說明。
若要結束調試程式,您可以使用 [停止] (q) 。
從 PowerShell 5.0 開始,您可以執行 Exit 命令來結束您執行 或 Debug-Runspace
啟動Debug-Job
的巢狀偵錯會話。
藉由使用這些調試程式命令,您可以執行腳本、停止關注點、檢查變數的值和系統的狀態,然後繼續執行腳本,直到您發現問題為止。
注意:如果您逐步執行具有重新導向運算子的語句,例如 “>”,PowerShell 調試程式會逐步執行腳本中所有剩餘的語句。
顯示文稿變數的值
當您在調試程式中時,也可以輸入命令、顯示變數的值、使用 Cmdlet,以及在命令行執行腳本。
您可以在正在偵錯的文稿中顯示所有變數的目前值,但下列自動變數除外:
$_
$Args
$Input
$MyInvocation
$PSBoundParameters
如果您嘗試顯示上述任何變數的值,您會取得偵錯工具所使用之內部管線中的變數值,而不是指令碼中的變數值。
若要針對正在偵錯的腳本顯示這些變數的值,請在腳本中,將自動變數的值指派給新的變數。 然後,您可以顯示新變數的值。
例如
$scriptArgs = $Args
$scriptArgs
在本主題的範例中,變數的值 $MyInvocation
會重新指派,如下所示:
$scriptname = $MyInvocation.MyCommand.Path
調試程序環境
當您到達斷點時,請輸入調試程序環境。 命令提示字元會變更,使其以 “[DBG]:” 開頭。 如果您要偵錯工作流程,提示為 “[WFDBG]”。 您可以自訂提示。
如需自定義提示的詳細資訊,請參閱 about_Prompts。
此外,在某些主機應用程式中,例如PowerShell控制台, (但不在Windows PowerShell整合式腳本環境 [ISE]) 中,巢狀提示會開啟以進行偵錯。 您可以透過在命令提示字元出現 (ASCII 62) 重複的字元來偵測巢狀提示。
例如,以下是 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-Variable
Cmdlet 的 Get-Alias
Scope 參數。
例如,下列命令會取得本機 (腳稿) 範圍的變數:
Get-Variable -scope 0
您可以將命令縮寫為:
gv -s 0
這是只查看您在文稿中定義的變數,以及在偵錯時定義的實用方式。
命令行上的偵錯
當您設定變數斷點或命令斷點時,只能在腳本檔案中設定斷點。 不過,根據預設,斷點會在目前會話中執行的任何項目上設定。
例如,如果您在變數上 $name
設定斷點,調試程式會中斷任何腳本、命令、函式、腳本 Cmdlet 或表達式中執行的任何 $name
變數,直到您停用或移除斷點為止。
這可讓您在更實際的內容中偵錯腳本,這些腳本可能會受到會話和使用者配置檔中的函式、變數和其他腳本影響。
行斷點是腳本檔案特有的,因此它們只會在腳本檔案中設定。
偵錯工作流程
PowerShell 4.0 調試程式可用來對 PowerShell 工作流程進行偵錯,不論是在 PowerShell 控制台或 Windows PowerShell ISE 中。 使用PowerShell調試程式來偵錯工作流程有一些限制。
- 您可以在調試程式中檢視工作流程變數,但不支援從調試程式內設定工作流程變數。
- 無法在工作流程調試程式中停止時完成索引標籤。
- 工作流程偵錯只適用於從PowerShell腳本同步執行的工作流程。 如果工作流程是以作業 (的形式執行,則無法使用 AsJob 參數) 進行偵錯。
- 不會實作其他巢狀偵錯案例,例如呼叫另一個工作流程的工作流程或呼叫腳本的工作流程。
下列範例示範如何偵錯工作流程。 當調試程式逐步執行工作流程函式時,調試程式提示會變更為 “[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:"
# +!INCLUDE[]~~~~~
[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
# +!INCLUDE[]~
[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:"
# +!INCLUDE[]~~~~~~~~~
[WFDBG:localhost]: PS C:>> stepOut
Get PowerShell process:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
433 35 106688 128392 726 2.67 7124 powershell
499 44 134244 172096 787 2.79 7452 powershell
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>
偵錯遠端文本
從 PowerShell 5.0 開始,您可以在遠端會話、控制台或 #D302E8A8F36B6474D809747CA14309ABB ISE 中執行 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>
範例
此測試文本會偵測操作系統的版本,並顯示系統適當的訊息。 它包含函式、函數調用和變數。
下列命令會顯示測試文稿檔案的內容:
PS C:\PS-test> Get-Content test.ps1
function psversion {
"PowerShell " + $PSVersionTable.PSVersion
if ($PSVersionTable.PSVersion.Major -lt 6) {
"Upgrade to PowerShell 6.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”。
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-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
# DBG>
顯示變數的 $scriptName
目前值,也就是 $null
。
DBG> $scriptName
# DBG>
使用步驟命令 () 來執行填入變數的語句。
然後,顯示變數的新值 $scriptName
。
DBG> $scriptName
C:\ps-test\test.ps1
```powershell
Use a Step command (s) to preview the next statement in the script.
```powershell
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-PSBreakpoint
和 Remove-PSBreakpoint
Cmdlet。
PS C:\ps-test> Get-PSBreakpoint| Remove-PSBreakpoint
Create 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 參數來設定斷點執行的條件,或執行準備或診斷工作,例如啟動記錄或叫用診斷或安全性腳本。
若要設定動作,請使用 [繼續] 命令 (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=[]
此範例只示範幾個使用PowerShell調試程式的方式。
如需調試程式 Cmdlet 的詳細資訊,請輸入下列命令:
help <cmdlet-name> -full
例如,輸入:
help Set-PSBreakpoint -full
PowerShell 中的其他偵錯功能
除了 PowerShell 調試程式之外,PowerShell 還包含數個可用來偵錯腳本和函式的其他功能。
Windows PowerShell ISE 包含互動式圖形化調試程式。 如需詳細資訊,請啟動 Windows PowerShell ISE,然後按 F1。
Cmdlet
Set-PSDebug
提供非常基本的腳本偵錯功能,包括逐步執行和追蹤。Set-StrictMode
使用 Cmdlet 來偵測未初始化變數的參考、對物件不存在屬性的參考,以及無效的函式語法。將診斷語句新增至腳本,例如顯示變數值的語句、從命令行讀取輸入的語句,或報告目前指令的語句。 使用包含此工作的 Write 動詞指令的 Cmdlet,例如
Write-Host
、Write-Debug
、Write-Warning
和Write-Verbose
。