共用方式為


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