次の方法で共有


about_Debuggers

簡単な説明

PowerShell デバッガーについて説明します。

詳細な説明

デバッグは、スクリプトの実行中にスクリプトを調べて、スクリプト命令のエラーを特定して修正するプロセスです。 PowerShell デバッガーは、スクリプト、関数、コマンド、PowerShell Desired State Configuration (DSC) 構成、または式のエラーと非効率性を調べて特定するのに役立ちます。

PowerShell 5.0 以降、PowerShell デバッガーは、リモート コンピューター上のコンソールまたは Windows PowerShell Integrated Scripting Environment (ISE) で実行されているスクリプト、関数、コマンド、構成、または式をデバッグするように更新されました。

Note

Windows PowerShell ISE では、Windows PowerShell のみがサポートされます。 PowerShell 6 以降では、PowerShell の拡張機能と共に Visual Studio Code を使用する必要があります。 詳細については、「 Debugging with Visual Studio Code」を参照してください。

デバッガー コマンドレット

PowerShell デバッガーには、次のコマンドレットのセットが含まれています。

  • Set-PSBreakpoint: 行、変数、およびコマンドにブレークポイントを設定します。
  • Get-PSBreakpoint: 現在のセッションのブレークポイントを取得します。
  • Disable-PSBreakpoint: 現在のセッションのブレークポイントをオフにします。
  • Enable-PSBreakpoint: 現在のセッションでブレークポイントを再び有効にします。
  • Remove-PSBreakpoint: 現在のセッションからブレークポイントを削除します。
  • Get-PSCallStack: 現在の呼び出し履歴を表示します。

デバッガーの起動と停止

デバッガーを起動するには、1 つ以上のブレークポイントを設定し、デバッグするスクリプト、コマンド、または関数を実行します。

ブレークポイントに到達すると、実行が停止し、制御がデバッガーに引き継がれます。

デバッガーを停止するには、完了するまでスクリプト、コマンド、または関数を実行します。 または、「 stop または t」と入力します。

デバッガー コマンド

PowerShell コンソールでデバッガーを使用する場合は、次のコマンドを使用して実行を制御します。 Windows PowerShell ISE で、[デバッグ] メニューのコマンドを使用します。

Note

他のホスト アプリケーションでデバッガーを使用する方法については、ホスト アプリケーションのドキュメントを参照してください。

  • sStepInto: 次のステートメントを実行し、停止します。

  • vStepOver: 次のステートメントを実行しますが、関数と呼び出しはスキップします。 スキップしたステートメントは実行されますが、ステップ スルーされることはありません。

  • Ctrl+Break: (ISE ですべて中断) PowerShell コンソールまたは Windows PowerShell ISE 内で実行中のスクリプトに分割します。 Windows PowerShell 2.0、3.0、4.0 の Ctrl+Break はプログラムを閉じます。 Break All は、ローカルスクリプトとリモートスクリプトの両方で動作します。

  • oStepOut: 現在の関数からステップ アウトします。入れ子になっている場合は 1 レベル上げます。 本体内にある場合は、末尾または次のブレークポイントに進みます。 スキップしたステートメントは実行されますが、ステップ スルーされることはありません。

  • cContinue: スクリプトが完了するまで、または次のブレークポイントに達するまで、実行を続行します。 スキップしたステートメントは実行されますが、ステップ スルーされることはありません。

  • lList: 実行中のスクリプトの部分を表示します。 既定では、現在の行、前の 5 行、および 10 行が表示されます。 スクリプトの一覧を表示するには、Enter キーを押します。

  • l <m>List: <m>で指定された行番号で始まるスクリプトの 16 行を表示します。

  • l <m> <n>List: <m>で指定された行番号で始まる、スクリプトの<n>行を表示します。

  • qStopExit: スクリプトの実行を停止し、デバッガーを終了します。 Debug-Job コマンドレットを実行してジョブをデバッグする場合、Exit コマンドはデバッガーをデタッチし、ジョブの実行を続行できるようにします。

  • kGet-PsCallStack: 現在の呼び出し履歴を表示します。

  • <Enter>: 最後のコマンドが Step (s)、 StepOver (v)、または List (l) であった場合に繰り返します。 それ以外の場合は、送信アクションを表します。

  • ?h: デバッガー コマンドのヘルプを表示します。

デバッガーを終了するには、 Stop (q) を使用できます。

PowerShell 5.0 以降では、Exit コマンドを実行して、 Debug-Job または Debug-Runspaceを実行して開始した入れ子になったデバッグ セッションを終了できます。

これらのデバッガー コマンドを使用すると、スクリプトの実行、懸念点での停止、変数の値とシステムの状態の確認、問題が特定されるまでスクリプトの実行を続けることができます。

Note

>などのリダイレクト演算子を使用してステートメントにステップ インすると、PowerShell デバッガーはスクリプト内の残りのすべてのステートメントをステップ実行します。

スクリプト変数の値の表示

デバッガーの実行中は、コマンドを入力したり、変数の値を表示したり、コマンドレットを使用したり、コマンド ラインでスクリプトを実行したりすることもできます。 次の自動変数を除き、デバッグ対象のスクリプト内のすべての変数の現在の値を表示できます。

$_
$Args
$Input
$MyInvocation
$PSBoundParameters

これらの変数の値を表示すると、スクリプト内の変数の値ではなく、デバッガーが使用する内部パイプラインの変数の値を取得します。

デバッグ中のスクリプトのこれらの変数の値を表示するには、スクリプトに行を追加して、これらの値を新しい変数に保存します。 これらの新しい行の後にブレークポイントを設定します。 その後、新しい変数の値を表示できます。

たとえば、 にします。

$scriptArgs = $Args
$scriptname = $MyInvocation.PSCommandPath

デバッガー環境

ブレークポイントに到達すると、デバッガー環境に入ります。 コマンド プロンプトが "[DBG]:" で始まるよう変更されます。 また、PowerShell コンソールなどの一部のホスト アプリケーションでは、デバッグ用に入れ子になったプロンプトが開きます。 入れ子になったプロンプトは、コマンド プロンプトに表示される繰り返し大きい文字 (ASCII 62) で検出できます。

プロンプトのカスタマイズの詳細については、 about_Promptsを参照してください。

入れ子のレベルは、 $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-Alias または Get-Variable コマンドレットの Scope パラメーターを使用します。

たとえば、次のコマンドは、ローカル (スクリプト) スコープ内の変数を取得します。

Get-Variable -scope 0

これは、スクリプトで定義した変数と、デバッグ中に定義した変数のみを表示する便利な方法です。

コマンド ラインでのデバッグ

変数ブレークポイントまたはコマンド ブレークポイントを設定する場合は、スクリプト ファイル内でのみブレークポイントを設定できます。 ただし、既定では、ブレークポイントは現在のセッションで実行されるすべてのものに設定されます。

たとえば、 $name 変数にブレークポイントを設定すると、ブレークポイントを無効または削除するまで実行するスクリプト、コマンド、関数、スクリプト コマンドレット、または式内の任意の $name 変数でデバッガーが中断されます。

これにより、より現実的なコンテキストでスクリプトをデバッグできます。このコンテキストでは、セッションおよびユーザーのプロファイル内の関数、変数、およびその他のスクリプトの影響を受ける可能性があります。

行ブレークポイントはスクリプト ファイルに固有であるため、スクリプト ファイルでのみ設定されます。

デバッグ関数

beginprocess、および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>

リモート スクリプトのデバッグ

Enter-PSSessionを実行して、リモート コンピューターにブレークポイントを設定したり、スクリプト ファイルやコマンドをデバッグしたりできる対話型のリモート PowerShell セッションを開始できます。 Enter-PSSession では、リモート コンピューターでスクリプトまたはコマンドを実行している切断されたセッションを再接続できます。 実行中のスクリプトがブレークポイントにヒットすると、クライアント セッションによってデバッガーが自動的に開始されます。 スクリプトを実行している切断されたセッションが既にブレークポイントに達している場合、 Enter-PSSession セッションに再接続すると、コマンド ライン デバッガーが自動的に開始されます。

この動作の例を次に示します。 ブレークポイントは、スクリプトの 6 行目、11 行目、22 行目、25 行目に設定されています。 デバッガーが起動すると、プロンプトに対して次の 2 つの変更が識別されます。

  • セッションが実行されているコンピューターの名前
  • デバッグ モードであることを知らせる 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>

このテスト スクリプトは、PowerShell のバージョンを検出し、バージョンに適したメッセージを表示します。 これには、関数、関数呼び出し、変数が含まれます。

次のコマンドは、テスト スクリプト ファイルの内容を表示します。

PS C:\PS-test>  Get-Content test.ps1

function psversion {
  "PowerShell " + $PSVersionTable.PSVersion
  if ($PSVersionTable.PSVersion.Major -lt 7) {
    "Upgrade to PowerShell 7!"
  }
  else {
    "Have you run a background job today (start-job)?"
  }
}

$scriptName = $MyInvocation.PSCommandPath
psversion
"Done $scriptName."

開始するには、行、コマンド、変数、関数など、スクリプト内の関心のある場所にブレークポイントを設定します。

まず、現在のディレクトリの Test.ps1 スクリプトの最初の行に行ブレークポイントを作成します。

PS C:\ps-test> Set-PSBreakpoint -line 1 -script 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.PSCommandPath

この時点で、 $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 コマンドレットを使用します。 (ブレークポイントを再利用する可能性があると思われる場合は、Remove-PsBreakpointの代わりに Disable-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.PSCommandPath
DBG>

$null$scriptName変数の現在の値を表示します。

DBG> $scriptName
DBG>

Step コマンド (s) を使用して、変数を設定するステートメントを実行します。 次に、 $scriptName 変数の新しい値を表示します。

DBG> $scriptName
C:\ps-test\test.ps1

Step コマンドを使用して、スクリプト内の次のステートメントをプレビューします。

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 コマンドレットを使用します。

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>

スクリプトは、関数呼び出しでブレークポイントに到達します。 この時点で、関数はまだ呼び出されていません。 これにより、 Set-PSBreakpoint の Action パラメーターを使用して、ブレークポイントの実行条件を設定したり、ログの開始や診断またはセキュリティ スクリプトの呼び出しなどの準備タスクや診断タスクを実行したりできます。

アクションを設定するには、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 キーワードを使用して、デバッガーを中断せずに実行するように指示することもできます。 既定のキーワードは 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 コマンドレットまたは Get-PsCallStack デバッガー コマンド (k) を使用します。 次のコマンドは、現在の呼び出し履歴を取得します。

DBG> k
2: prompt
1: .\test.ps1: $args=[]
0: prompt: $args=[]

この例では、PowerShell デバッガーを使用するさまざまな方法のほんの一部を示します。

PowerShell のその他のデバッグ機能

PowerShell デバッガーに加えて、PowerShell には、スクリプトと関数のデバッグに使用できる他のいくつかの機能が含まれています。

  • Set-PSDebug コマンドレットには、ステップ実行やトレースなど、非常に基本的なスクリプト デバッグ機能が用意されています。

  • Set-StrictMode コマンドレットを使用して、初期化されていない変数への参照、オブジェクトの存在しないプロパティへの参照、および無効な関数構文への参照を検出します。

  • 変数の値を表示するステートメント、コマンド ラインから入力を読み取るステートメント、現在の命令を報告するステートメントなど、診断ステートメントをスクリプトに追加します。 Write-HostWrite-DebugWrite-WarningWrite-Verboseなど、このタスクの書き込み動詞を含むコマンドレットを使用します。

関連項目