關於偵錯工具
簡短描述
說明 PowerShell 偵錯工具。
詳細描述
「偵錯工具」是在執行腳本以識別和更正腳本指示中的錯誤時,檢查腳本的過程。 PowerShell 偵錯工具可協助您檢查和識別腳本、函式、命令、PowerShell 工作流程、PowerShell Desired State Configuration (DSC)設定或運算式中的錯誤和效率不佳。
從 PowerShell 5.0 開始,PowerShell 偵錯工具已更新為在遠端電腦上的主控台或 Windows PowerShell ISE 中執行的 debug 腳本、函數、工作流程、命令、設定或運算式。 您可以執行 Enter-PSSession
來啟動互動式遠端 PowerShell 會話,您可以在遠端電腦上設定中斷點和偵錯工具腳本檔案和命令。 Enter-PSSession
功能已更新為可讓您重新連線到,並輸入在遠端電腦上執行腳本或命令的中斷連線會話。 如果執行中的腳本叫用中斷點,則您的用戶端會話會自動啟動偵錯工具。 如果執行腳本的已中斷連線會話已經到達中斷點,並在中斷點停止,則在 Enter-PSSession
您重新連線到會話之後,會自動啟動命令列偵錯工具。
PowerShell 偵錯工具也可以用來在 powershell 主控台或 Windows PowerShell ISE 中,用來偵測 PowerShell 工作流程。 從 PowerShell 5.0 開始,您可以在本機或遠端的執行中作業或進程中進行偵錯工具。
當 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 中中斷為執行中的腳本。 請注意Ctrl, + Windows PowerShell 2.0、3.0 和4.0 中的 CtrlBreak會關閉程式。 全部中斷都適用于本機和遠端互動執行的腳本。o
,StepOut
:跳出目前函式的步驟; 如果是 nested,則向上一層。 如果在主要主體中,它會繼續到結尾或下一個中斷點。 這會執行已跳過的陳述式,但不會逐步執行。c
、Continue
:會繼續執行,直到腳本完成或到達下一個中斷點為止。 這會執行已跳過的陳述式,但不會逐步執行。l
,List
:顯示正在執行之腳本的部分。 根據預設,它會顯示目前這一行、前五行,以及10個後續的行。 若要繼續列出腳本,請按 ENTER。l <m>
,List
:顯示16行的腳本,開頭為所指定的行號<m>
。l <m> <n>
,List
:顯示<n>
腳本的行,從指定的行號開始<m>
。q
、Stop
、Exit
:會停止執行腳本,並結束偵錯工具。 如果您藉由執行 Cmdlet 來進行作業的調試Debug-Job
程式,此命令會中斷調試Exit
程式的連結,並允許作業繼續執行。k
,Get-PsCallStack
:顯示目前的呼叫堆疊。<Enter>
:如果是步驟、跨距(v)或清單(l),則重複最後一個命令。 否則,表示提交動作。?
,h
:顯示偵錯工具命令說明。
若要結束偵錯工具,您可以使用 Stop (q)。
從 PowerShell 5.0 開始,您可以執行 [結束] 命令來結束執行或的已啟動的嵌套偵錯工具 Debug-Job
Debug-Runspace
。
藉由使用這些偵錯工具命令,您可以執行腳本、停止關注點、檢查變數的值和系統的狀態,並繼續執行腳本,直到您找出問題為止。
注意:如果您逐步執行含有重新導向運算子的語句(例如 ">"),則 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)
調試和範圍
中斷偵錯工具並不會變更您操作的範圍,但當您到達腳本中的中斷點時,就會移入腳本範圍中。 腳本範圍是您執行偵錯工具之範圍的子系。
若要尋找腳本範圍中定義的變數和別名,請使用或 Cmdlet 的 Scope 參數 Get-Alias
Get-Variable
。
例如,下列命令會取得本機(腳本)範圍中的變數:
Get-Variable -scope 0
您可以將命令縮寫為:
gv -s 0
這是一種實用的方式,只會查看您在腳本中定義的變數,以及在進行偵錯工具時所定義的變數。
在命令列中進行偵錯工具
當您設定變數中斷點或命令中斷點時,只能在腳本檔案中設定中斷點。 不過,根據預設,中斷點會在目前會話中執行的任何專案上設定。
例如,如果您在變數上設定中斷點 $name
,偵錯工具會在您 $name
執行的任何腳本、命令、函式、腳本 Cmdlet 或運算式中中斷任何變數,直到您停用或移除中斷點為止。
這可讓您在更實際的內容中進行程式碼剖析,而這些腳本可能會受到會話和使用者設定檔中的函式、變數和其他腳本所影響。
行中斷點是腳本檔案特有的,因此只會在腳本檔案中設定。
偵錯工作流程
PowerShell 4.0 偵錯工具可用來在 powershell 主控台或 Windows PowerShell ISE 中,用來偵測 PowerShell 工作流程。 使用 PowerShell 偵錯工具來處理工作流程有一些限制。
- 當您在偵錯工具中時,可以查看工作流程變數,但不支援從偵錯工具內設定工作流程變數。
- 在工作流程偵錯工具中停止時,Tab 鍵自動完成無法使用。
- 工作流程的調試只適用于從 PowerShell 腳本同步執行工作流程。 如果工作流程是以工作的形式執行(使用AsJob參數),您就無法將它們進行 debug。
- 其他的嵌套調試情況(例如呼叫另一個工作流程的工作流程或呼叫腳本的工作流程)則不會執行。
下列範例示範如何對工作流程進行調試。 當偵錯工具逐步執行工作流程函式時,偵錯工具提示字元會變更為 "[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 開始,您可以在遠端會話、主控台或 Windows PowerShell 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 命令來執行腳本中的第一個語句,並預覽下一個語句。 下一個語句會使用 $MyInvocation
自動變數,將變數的值設定 $scriptName
為腳本檔案的路徑和檔案名。
DBG> s
test.ps1:11 $scriptName = $MyInvocation.MyCommand.Path
此時, $scriptName
系統不會填入變數,但是您可以藉由顯示變數的值來驗證其值。 此處的值為 $null
。
DBG> $scriptname
# DBG>
使用其他步驟命令來執行目前的語句,並預覽腳本中的下一個語句。 下一個語句會呼叫 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
Debug 訊息包含函數中語句的預覽。 若要執行此語句並預覽函式中的下一個語句,您可以使用 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>
使用 Step 命令來執行填入變數的語句。
然後,顯示新的 $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 函數的呼叫。 若要略過函式但仍執行它,請使用跨距命令(v)。 如果您在使用跨距時已經在函式中,則不會生效。 會顯示函式呼叫,但不會執行它。
DBG> v
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13 "Done $scriptName"
跨距命令會執行函數,並預覽腳本中的下一個語句,這會列印最後一行。
使用停止命令(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>
腳本會到達函式呼叫的中斷點。 此時,尚未呼叫函數。 這讓您有機會使用的 Action 參數 Set-PSBreakpoint
來設定中斷點執行的條件,或是執行準備或診斷工作,例如開機記錄或叫用診斷或安全性腳本。
若要設定動作,請使用 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 關鍵字來指示偵錯工具在不中斷的情況下執行。 因為 default 關鍵字會繼續,所以您必須指定 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。
此
Set-PSDebug
Cmdlet 提供非常基本的腳本調試功能,包括逐步執行和追蹤。使用
Set-StrictMode
Cmdlet 來偵測未初始化變數的參考、物件不存在之屬性的參考,以及不正確函數語法。將診斷語句加入至腳本,例如顯示變數值的語句、從命令列讀取輸入的語句,或報告目前指令的語句。 使用包含此工作之寫入動詞的 Cmdlet,例如
Write-Host
、Write-Debug
、Write-Warning
和Write-Verbose
。