PowerShellのコマンドラインセッション内でデバッグしてみる

PowerShellスクリプトのデバッグは、`Visual Stuido Code`+`PowerShell拡張`で提供されている機能を利用することによりエディタ上でデバックを行うことができます。

これとは別に、`PowerShell`ではデバック用のコマンドレットが用意されており。　これらのコマンドレットを利用することによりコマンドラインセッション上でデバックをする事ができます。

今回はデバック用コマンドレットを利用して、コマンドラインセッション上でデバックをしてみます。

## ドキュメント

[about_Debuggers](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_debuggers?view=powershell-7.2)

[debugging-from-commandline.md](https://github.com/PowerShell/PowerShell/blob/master/docs/learning-powershell/debugging-from-commandline.md)

## 実行環境

- Windows 21H2
- 7.3.0-preview.6

## コマンドレットでデバックしてみる

```PowerShell:c:\temp\test.ps1
[string]$var1 = "hello"
[string]$var2 = "world"
[string]$var3 = $var1 + $var2

Write-Host "var1:$var1"
Write-Host "var2:$var2"
Write-Host "var3:$var3"

[int]$int1=100
[int]$int2=100
[int]$int3=$int1 * $int2

Write-Host "int1:$int1"
Write-Host "int2:$int2"
Write-Host "int3:$int3"
```

今回、上記のPowerShellスクリプトをデバッグで利用してみます。

`c:\temp\test.ps1`の1行目に`Set-PSBreakpoint`でブレイクポイントを設定します。

`Set-PSBreakpoint =Line 1 -Script c:\temp\test.ps1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/64182e65-f35f-a925-5da7-3644a70b4ef9.png)

ブレイクポイントが設定された状態で、`test.ps1`を実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/f0527318-aeb0-d854-5c24-665cb5763249.png)

1行目にブレイクポイントを設定したので、ヒットして処理がとまり。
`[DBG]:`と入力を受け付ける状態となりました。

表示されたコメントに`h` or `?` でhelpがみれると記載されているので実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/8e3612df-5a84-8c70-6ae6-d85c5e57cd46.png)


ステップイン、ステップオーバー、ステップアウトするには `s` , `v` , `o`
処理継続 `c`
処理を抜ける `q`
ソースコードの確認は`l`

でできるようです。

lを入力してソースコードを確認してみます。

ソースコードが表示されました、また1行名に`＊`がついていますが、これが現在の行を表しているようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/c1cd91af-bdd5-a4f4-5a02-f6c5713a4a4c.png)

今現在、1行目が実行前の状態となるので、この状態で`get-variable "var*" , "int*"`と入力して、現在の変数の状態を確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/800ac071-3654-8724-7833-270b57ba57bc.png)

1行目が実行前の状態なので、スクリプト中でつかっている var1,var2,var3,int1,int2,int3の変数がまだGet-Variableコマンドレットでは表示されない事が確認できます。

`s`でステップインをしてから、もう一度Get-Variableコマンドレットで変数を取得してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/afa23f51-f99f-7ab5-299e-0e40e2ae7cba.png)

ステップインで2行目に移動したため、1行目の`[string]$var1 = "hello"`が実行され変数$var1がGet-Variableコマンドレットに表示されるようになりました。

これでコマンドラインセッション内でデバッグができる事を確認できたかと思います。

あとは適宜ステップを進めていき、変数の状態や処理を確認したり。
`q`で画面を抜けたり、`c`で処理を継続したり操作を行います。

## 設定しているブレイクポイントを確認・削除してみる

`Get-PSBreakpoint`コマンドレットで現在設定されているブレイクポイントが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/3dc45bf7-95cc-d831-d3bd-d02619e5036d.png)

ここで確認できる一覧をパイプで`Remove-PSBreakpoint`で渡せば、設定されているブレイクポイントを一括で解除する事ができます。

`Get-PSBreakpoint | Remove-PSBreakpoint`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/31ebd635-49df-de01-ed0e-8bd68dbd5471.png)

## 設定しているブレイクポイントを無効化・有効化してみる

ブレイクポイントを削除するだけでなく、`Disable-PSBreakpoint`、`Enable-PSBreakpoint`コマンドレットを使い無効化、有効化をすることもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/8bef8eca-27c6-4a4a-6c28-ed39a9a17852.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/cf0737ef-8128-63f8-c016-c40dd4e94bb7.png)

## 色々な条件のブレイクポイントを設定してみる

まずは`test.ps1`の1行目にブレイクポイントを設定して、動き方を確認してみましたが。

Set-PSBreakpointでは

- 行ブレイクポイント(-Line)
- コマンドブレイクポイント(-Command)
- 変数ブレイクポイント（-Variable）

が利用できます。

### 行ブレイクポイント

さきほどやりましたが、行ブレイクポイントはLineオプションで行ブレイクポイントを設定します。

`Set-PSBreakpoint =Line 1 -Script c:\temp\test.ps1`

### コマンドブレイクポイント

コマンドブレイクポイントはCommandオプションを利用して設定します。

今回は`Set-PSBreakpoint -Command "Write-Host" -Script C:\temp\test.ps1`とし、`Write-Host`にブレイクポイントを設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/5a6f8b9c-f86a-aed7-eff3-ad609a4ebebc.png)

この状態で`c:\temp\test.ps1`を実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/1bbf2f69-7f90-163e-7425-218961a227b5.png)

5行目のWrite-Hostでブレイクされた事が確認できます。
この状態で継続`c`を入力すれば、次にWrite-Hostが出てくる所でまたとまります。

### 変数ブレイクポイント

変数ブレイクポイントではVariableオプションで変数名を指定し、Modeオプションで変数が読み書きされた時にブレイクするように設定します。

今回は変数int1が読み書きされる際にブレイクするよう設定してみました。

`Set-PSBreakpoint -Variable "int1" -Mode ReadWrite -Script C:\temp\test.ps1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/134548fb-f88d-405a-aa8d-2836a19fa802.png)

この状態で`c:\temp\test.ps1`を実行すると、9行目で変数int1に値を代入しようとする所でブレイクされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/b0bfce3c-bbfb-dfdd-2cc3-10fbfaa5169a.png)

## 総評

PowerShellプロンプトで作業中にほんのちょっとデバッグしたい等の時に、これを知っておけば便利かと思います。