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 主控台中使用偵錯工具時,請使用下列命令控制執行作
業。
注意:如需如何在其他主機應用程式中使用偵錯工具的詳細資訊,請參閱該主機應
用程式說明文件。
v, Step-over 執行下一個陳述式,但略過函數和呼叫。略過的陳述式會
被執行,但不會進行逐步執行。
o, Step-out 跳離目前的函數,如果是巢狀結構則跳回上一層。如果是
在內文中,就會繼續到結尾處或是下一個中斷點。略過的
陳述式會被執行,但不會進行逐步執行。
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) {"偵錯"} else {"非偵錯"}
您可以在偵錯過程中使用 $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 "開始"
}
process
{
write-output "處理"
}
end
{
write-output "結束"
}
}
C:\PS> set-psbreakpoint -command test-cmdlet
C:\PS> test-cmdlet
開始
即將進入偵錯模式。請使用 h 或 ? 以取得說明。
叫用在 'prompt:test-cmdlet' 上的命令中斷點
test-cmdlet
[DBG]: C:\PS> c
處理
即將進入偵錯模式。請使用 h 或 ? 以取得說明。
叫用在 'prompt:test-cmdlet' 上的命令中斷點
test-cmdlet
[DBG]: C:\PS> c
結束
即將進入偵錯模式。請使用 h 或 ? 以取得說明。
叫用在 'prompt:test-cmdlet' 上的命令中斷點
test-cmdlet
[DBG]: C:\PS>
偵錯遠端指令碼
您無法在遠端工作階段中執行 Windows PowerShell 偵錯工具。若要偵錯遠端電腦
上的指令碼,請將指令碼複製到本機電腦。
下列命令會從 Server01 遠端電腦,將 Test.ps1 指令碼複製到本機電腦:
invoke-command -computername Server01 `
{get-content c:\ps-test\test.ps1} | set-location c:\ps-test\test.ps1
範例
這個測試指令碼會偵測作業系統的版本,並顯示 system-appropriate 訊息。其中
包含函數、函數呼叫和變數。
下列命令會顯示測試指令檔的內容:
c:>\PS-test> get-content test.ps1
function psversion {
"Windows Powershell " + $psversiontable.psversion
if ($psversiontable.psversion.major -lt 2) {
"升級到 Windows PowerShell 2.0!"
}
else {
"您今天有執行背景工作 (start-job) 嗎?"
}
}
$scriptname = $MyInvocation.MyCommand.Path
psversion
"完成 $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)。
欄 : 0
行 : 1
動作 :
啟用 : True
HitCount : 0
Id : 0
Script : C:\ps-test\test.ps1
ScriptName : C:\ps-test\test.ps1
現在,請啟動指令碼。
PS C:\ps-test> .\test.ps1
當指令碼抵達第一個中斷點時,中斷點訊息會指出偵錯工具正在作用中。其中會描
述中斷點並預覽指令碼的第一行,該行是函數宣告。命令提示字元也會變更,指出
偵錯工具擁有控制權。
預覽行包含指令碼名稱和所預覽命令的行號。
即將進入偵錯模式。請使用 h 或 ? 以取得說明。
叫用在 '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>
使用 another Step 命令 (s) 執行指令碼中目前的陳述式並預覽下一個陳述式。
下一個陳述式會呼叫 PsVersion 函數。
DBG> s
test.ps1:12 psversion
這時已經填入 $ScriptName 變數,但您可以藉由顯示變數值來確認其值。在這
裡,該值是設定為指令碼路徑。
DBG> $scriptname
C:\ps-test\test.ps1
使用 another Step 命令執行函數呼叫。請按 ENTER 或輸入 "s" 進行 Step。
DBG> s
test.ps1:2 "Windows Powershell " + $psversiontable.psversion
偵錯訊息包含函數的陳述式預覽。
若要執行這個陳述式並預覽函數的下一個陳述式,您可以使用 Step 命令。但是,
在這裡,請使用 Step-Out 命令。這樣會完成函數的執行 (除非抵達中斷點),
並逐步執行到指令碼的下一個陳述式。
DBG> o
Windows Powershell 2.0
您今天有執行背景工作 (start-job) 嗎?
test.ps1:13 "完成 $scriptname"
因為我們正位於指令碼的最後一個陳述式,所以 Step、Step-Out 和 Continue 命
令具有相同的效果。在這裡,請使用 Step-Out (o)。
完成 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
叫用在 'C:\ps-test\test.ps1:$scriptname' 上的變數中斷點 (寫入存取權)
test.ps1:11 $scriptname = $MyInvocation.mycommand.path
DBG>
顯示 $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
您今天有執行背景工作 (start-job) 嗎?
test.ps1:13 "完成 $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
現在,請執行指令碼。<tab>
PS C:\ps-test> .\test.ps1
叫用在 'C:\ps-test\test.ps1:psversion' 上的命令中斷點
test.ps1:12 psversion
DBG>
指令碼抵達函數呼叫的中斷點。此時尚未呼叫函數。這讓您有機會使用
Set-PsBreakpoint 的 Action 參數,設定中斷點執行的條件,或者是執
行準備或診斷工作,例如啟動記錄作業或呼叫診斷或安全性指令碼。
若要設定動作,請使用 Continue 命令 (c) 結束指令碼,以及
Remove-PsBreakpoint 命令刪除目前的中斷點 (中斷點是唯讀的,
所以您無法對目前的中斷點新增動作)。
DBG> c
Windows PowerShell 2.0
您今天有執行背景工作 (start-job) 嗎?
完成 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 "$scriptname `的值是 $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
叫用在 '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