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