「PowerShellスクリプトが思った通りに動かない…」
「エラーが出るけど、どこが悪いのかわからない…」
そんな経験はありませんか?プログラミングでは、こうした問題を「デバッグ」と呼び、原因を見つけて修正することが大切です。
PowerShellには、そんな時に頼れるSet-PSDebug
というコマンドレットがあります。
これは、スクリプトの実行状況を詳細に可視化するための機能で、エラーの原因やロジックミスの特定に非常に役立ちます。
Set-PSDebugでできること
- スクリプトがどの順番で実行されているかを確認
- 変数にどんな値が入っているかをリアルタイムで表示
- 1行ずつ実行しながら問題箇所を特定
- エラーが起きる直前の状況を把握
本記事では、Set-PSDebug
の使い方をレベル別に段階的に解説し、よくある誤解や注意点もフォローしていきます。
Set-PSDebugの基本構文と引数を覚えよう

基本的な書き方
Set-PSDebug -Trace <レベル>
トレースレベルの意味
レベル | 内容 | 使用場面 |
---|---|---|
0 | トレースなし(デバッグモードオフ) | 通常の実行時 |
1 | 各コマンドの実行を表示 | 実行順序を確認したい時 |
2 | コマンドに加えて、変数展開の詳細も表示 | 変数の中身も知りたい時 |
実際に使ってみよう
# デバッグモードを有効にする
Set-PSDebug -Trace 1
これで、スクリプト実行時に各行の実行内容が出力されるようになります。
基本的な流れ
- デバッグモードを有効化:
Set-PSDebug -Trace 1
- スクリプトを実行:いつも通りにスクリプトを動かす
- デバッグ情報を確認:出力された情報で問題を特定
- デバッグモードを無効化:
Set-PSDebug -Off
ポイント
- Set-PSDebugは「スクリプトの裏側」を見せてくれるコマンド
- レベルによって表示される情報の詳しさが変わる
- 使い終わったら必ずオフにする
Set-PSDebug
は「スクリプトの裏側」を見せてくれるコマンド。次は、それぞれのトレースレベルの具体的な出力例を見てみましょう。
出力の違いを実際に確認してみよう
テスト用のスクリプト
まず、簡単なスクリプトを使って、各レベルでどんな情報が表示されるかを確認してみましょう。
# test.ps1
$name = "Taro"
$age = 25
Write-Output "Hello, $name! You are $age years old."
レベル1の出力例
Set-PSDebug -Trace 1
# test.ps1を実行
出力結果:
DEBUG: 1+ $name = "Taro"
DEBUG: 2+ $age = 25
DEBUG: 3+ Write-Output "Hello, $name! You are $age years old."
Hello, Taro! You are 25 years old.
レベル1でわかること:
- どの行が実行されているか
- コマンドの実行順序
- エラーが起きた行の特定
レベル2の出力例
Set-PSDebug -Trace 2
# test.ps1を実行
出力結果:
DEBUG: 1+ $name = "Taro"
DEBUG: 2+ $age = 25
DEBUG: 3+ Write-Output "Hello, $name! You are $age years old."
DEBUG: Hello, Taro! You are 25 years old.
Hello, Taro! You are 25 years old.
レベル2でわかること:
- 変数の中身がどう展開されているか
- 実際に実行される内容
- 計算結果や文字列の結合結果
複雑な例での比較
# complex.ps1
$numbers = @(1, 2, 3, 4, 5)
$sum = 0
foreach ($num in $numbers) {
$sum += $num
Write-Output "Current sum: $sum"
}
Write-Output "Final result: $sum"
レベル1の出力:
DEBUG: 1+ $numbers = @(1, 2, 3, 4, 5)
DEBUG: 2+ $sum = 0
DEBUG: 3+ foreach ($num in $numbers) { ...
DEBUG: 4+ $sum += $num
DEBUG: 5+ Write-Output "Current sum: $sum"
...
レベル2の出力:
DEBUG: 1+ $numbers = @(1, 2, 3, 4, 5)
DEBUG: 2+ $sum = 0
DEBUG: 3+ foreach ($num in $numbers) { ...
DEBUG: 4+ $sum += $num
DEBUG: $sum = 1
DEBUG: 5+ Write-Output "Current sum: $sum"
DEBUG: Current sum: 1
...
デバッグモードの終了方法
Set-PSDebug -Off
重要:デバッグモードを有効にしたままにしておくと、すべてのコマンドでデバッグ情報が表示されるため、必ず使い終わったらオフにしましょう。
実用的な使い方
エラーが起きるスクリプトの例
# error_example.ps1
$file_path = "C:\nonexistent\file.txt"
$content = Get-Content $file_path
Write-Output "File content: $content"
デバッグ実行:
Set-PSDebug -Trace 2
.\error_example.ps1
これにより、エラーが起きる直前のコマンドと変数の状態がわかります。
ポイント
- レベル1:実行順序の確認
- レベル2:変数の中身や処理結果まで追跡可能
- 複雑なスクリプトほどデバッグの効果が大きい
- 使い終わったら必ずオフにする
レベル2にすると、変数の中身や処理結果まで追跡可能に。次は、エラー時のステップイン機能とその活用法を見てみましょう。
ステップ実行でスクリプトの流れを把握しよう

ステップ実行ってなに?
Set-PSDebug -Step
を使うと、1行ずつ手動で実行しながらスクリプトを確認できます。これは、問題のある箇所をピンポイントで特定したい時に非常に便利です。
基本的な使い方
Set-PSDebug -Step
ステップ実行の流れ
スクリプトを実行すると、以下のようなプロンプトが表示されます:
DEBUG: Stepping into: $name = "Taro"
Enter to continue, 's' to step, 'q' to quit:
よく使う操作
入力 | 動作 | 説明 |
---|---|---|
Enter | 次の行へ進む | 最も基本的な操作 |
s | ステップイン | 関数の中身も1行ずつ実行 |
q | デバッグを終了 | ステップ実行を中断 |
実際の使用例
# step_example.ps1
function Calculate-Sum($a, $b) {
$result = $a + $b
Write-Output "Calculating: $a + $b = $result"
return $result
}
$x = 10
$y = 20
$sum = Calculate-Sum $x $y
Write-Output "Final answer: $sum"
ステップ実行してみよう:
Set-PSDebug -Step
.\step_example.ps1
実行中の表示:
DEBUG: Stepping into: function Calculate-Sum($a, $b) { ...
Enter to continue, 's' to step, 'q' to quit: [Enter押下]
DEBUG: Stepping into: $x = 10
Enter to continue, 's' to step, 'q' to quit: [Enter押下]
DEBUG: Stepping into: $y = 20
Enter to continue, 's' to step, 'q' to quit: [Enter押下]
DEBUG: Stepping into: $sum = Calculate-Sum $x $y
Enter to continue, 's' to step, 'q' to quit: s [s入力:関数の中に入る]
DEBUG: Stepping into: $result = $a + $b
Enter to continue, 's' to step, 'q' to quit: [Enter押下]
ステップ実行が便利な場面
1. 条件分岐の確認
$score = 85
if ($score -ge 90) {
Write-Output "Excellent!"
} elseif ($score -ge 70) {
Write-Output "Good!"
} else {
Write-Output "Need improvement."
}
ステップ実行で、どの条件に入るかを確認できます。
2. ループ処理のチェック
$items = @("apple", "banana", "cherry")
foreach ($item in $items) {
Write-Output "Processing: $item"
# 何らかの処理
}
各ループの実行を1つずつ確認できます。
3. エラーの原因特定
$data = @()
# $data に値を追加する処理(問題があるかも?)
$result = $data[0] # エラーが起きる可能性
エラーが起きる直前で変数の状態を確認できます。
トレースとステップの組み合わせ
# より詳細な情報を得るために両方を有効化
Set-PSDebug -Trace 2 -Step
これにより、変数の詳細情報を見ながら1行ずつ実行できます。
ステップ実行のコツ
1. 問題がありそうな箇所でステップ実行開始
# 通常実行
Write-Output "Script started"
$config = Load-Configuration
# ここから問題がありそう
Set-PSDebug -Step
$processed_data = Process-Data $config
$result = Save-Data $processed_data
Set-PSDebug -Off
# 通常実行に戻る
Write-Output "Script completed"
2. 複雑な関数の動作確認
function Complex-Calculation($input_data) {
# 複雑な処理がある関数
$step1 = $input_data | Where-Object { $_.Status -eq "Active" }
$step2 = $step1 | ForEach-Object { $_.Value * 2 }
$step3 = ($step2 | Measure-Object -Sum).Sum
return $step3
}
# この関数の動作を詳しく見たい
Set-PSDebug -Step
$result = Complex-Calculation $my_data
Set-PSDebug -Off
ポイント
- -Stepオプションは、問題のある行をピンポイントで探るのに最適
- ‘Enter’で進行、’s’でより詳しく、’q’で終了
- 複雑な処理や条件分岐の確認に便利
- 必要な箇所だけでステップ実行すると効率的
-Step
オプションは、問題のある行をピンポイントで探るのに最適。次は、Set-PSDebugの注意点や落とし穴について触れておきます。
Set-PSDebugの注意点と落とし穴を知っておこう

1. 実行速度が大幅に遅くなる
問題点
デバッグ情報の出力が多いため、処理がかなり遅く感じられることがあります。
# 大量のデータを処理するスクリプト
Set-PSDebug -Trace 2
$large_array = 1..10000
foreach ($item in $large_array) {
# 各ループでデバッグ情報が出力される
$result = $item * 2
}
対策方法
部分的なデバッグ実行:
# 問題がありそうな箇所のみデバッグ
Write-Output "Processing started..."
# 通常実行
$data = Load-LargeData
# ここだけデバッグ
Set-PSDebug -Trace 2
$filtered_data = $data | Where-Object { $_.Status -eq "Error" }
Set-PSDebug -Off
# 通常実行に戻る
Save-Results $filtered_data
サンプルデータでのテスト:
# 大量データではなく、少量のテストデータで確認
$test_data = $large_data | Select-Object -First 10
Set-PSDebug -Trace 2
# テストデータで動作確認
Set-PSDebug -Off
2. 変数の値がすぐに見えない?
よくある誤解
「変数に何が入っているかわからない」という時は、Traceレベル1では変数の展開結果が表示されません。
Set-PSDebug -Trace 1
$name = "Taro"
$message = "Hello, $name!"
Write-Output $message
レベル1の出力:
DEBUG: 1+ $name = "Taro"
DEBUG: 2+ $message = "Hello, $name!"
DEBUG: 3+ Write-Output $message
Hello, Taro!
変数の中身が見えません。
解決方法
レベル2を使用:
Set-PSDebug -Trace 2
$name = "Taro"
$message = "Hello, $name!"
Write-Output $message
レベル2の出力:
DEBUG: 1+ $name = "Taro"
DEBUG: 2+ $message = "Hello, $name!"
DEBUG: Hello, Taro!
DEBUG: 3+ Write-Output $message
DEBUG: Hello, Taro!
Hello, Taro!
手動でのチェック:
$name = "Taro"
Write-Output "Debug: name = $name" # 手動で変数の中身を表示
$message = "Hello, $name!"
Write-Output "Debug: message = $message"
3. 実行ポリシーの問題
問題点
Set-PSDebug
自体に制限はありませんが、スクリプト実行が許可されていない環境では使えません。
# エラー例
.\test.ps1
# エラー: このシステムではスクリプトの実行が無効になっています。
対策方法
一時的な実行許可:
# 現在のプロセスのみで実行を許可
Set-ExecutionPolicy RemoteSigned -Scope Process
# デバッグ実行
Set-PSDebug -Trace 2
.\test.ps1
Set-PSDebug -Off
実行ポリシーの確認:
Get-ExecutionPolicy
# Restricted: スクリプト実行不可
# RemoteSigned: 署名済みスクリプトまたはローカルスクリプト実行可能
4. 大量の出力で重要な情報が埋もれる
問題点
複雑なスクリプトでは、デバッグ情報が大量に出力されて、重要な部分が見つけにくくなります。
対策方法
ログファイルへの出力:
# デバッグ情報をファイルに保存
Set-PSDebug -Trace 2
.\my_script.ps1 *> debug_log.txt 2>&1
Set-PSDebug -Off
# ログファイルを後で確認
Get-Content debug_log.txt | Select-String "ERROR"
特定の処理のみデバッグ:
function Debug-Section($scriptblock, $description) {
Write-Output "=== Debugging: $description ==="
Set-PSDebug -Trace 2
& $scriptblock
Set-PSDebug -Off
Write-Output "=== End Debug: $description ==="
}
# 使用例
Debug-Section { $result = Complex-Calculation $data } "Data calculation"
Debug-Section { Save-Results $result } "Saving results"
5. デバッグモードを切り忘れる
問題点
デバッグモードを有効にしたまま忘れてしまうと、以降のすべてのコマンドでデバッグ情報が表示されます。
対策方法
確実な終了処理:
try {
Set-PSDebug -Trace 2
# スクリプトの処理
.\my_script.ps1
} finally {
# エラーが起きても必ずデバッグモードを解除
Set-PSDebug -Off
}
現在の状態確認:
# 現在のデバッグ設定を確認
$PSDebugPreference
# SilentlyContinue: デバッグオフ
# Continue: デバッグオン
デバッグ効率を上げるコツ
1. 問題箇所の特定
# エラーメッセージから問題の行を特定してからデバッグ
try {
.\my_script.ps1
} catch {
Write-Output "Error at line: $($_.InvocationInfo.ScriptLineNumber)"
Write-Output "Error message: $($_.Exception.Message)"
}
2. 段階的なデバッグ
# 1. まずは全体の流れを確認
Set-PSDebug -Trace 1
.\my_script.ps1
Set-PSDebug -Off
# 2. 問題がありそうな箇所を詳しく確認
Set-PSDebug -Trace 2
# 特定の部分だけ実行
Set-PSDebug -Off
# 3. 必要に応じてステップ実行
Set-PSDebug -Step
# 問題箇所を1行ずつ確認
Set-PSDebug -Off
ポイント
- 大量データでは処理が遅くなるので部分的にデバッグ
- 変数の詳細を見るにはレベル2が必要
- 実行ポリシーの確認と適切な設定
- デバッグモードの切り忘れに注意
- 段階的なアプローチで効率的にデバッグ
便利な反面、使い方や出力の量には注意が必要です。最後に、まとめと活用例を紹介して記事を締めます。
まとめ:Set-PSDebugでスクリプトの見える化を実現
主要コマンド一覧
コマンド | 説明 | 使用場面 |
---|---|---|
Set-PSDebug -Trace 1 | コマンドレベルの追跡 | 実行順序の確認 |
Set-PSDebug -Trace 2 | 変数評価も含めた詳細追跡 | 変数の中身も確認したい |
Set-PSDebug -Step | ステップ実行(1行ずつ確認) | 問題箇所のピンポイント特定 |
Set-PSDebug -Off | デバッグモード解除 | デバッグ終了時 |
効果的なデバッグの流れ
1. 問題の発見段階
# まずは軽くトレースレベル1で全体の流れを確認
Set-PSDebug -Trace 1
.\problematic_script.ps1
Set-PSDebug -Off
2. 詳細調査段階
# 変数の中身も含めて詳しく調査
Set-PSDebug -Trace 2
# 問題がありそうな部分だけ実行
Set-PSDebug -Off
3. ピンポイント特定段階
# 1行ずつ慎重に確認
Set-PSDebug -Step
# 特定の関数や処理を実行
Set-PSDebug -Off
実践的な活用例
ファイル処理スクリプトのデバッグ
# ファイル処理でエラーが起きる場合
function Process-Files($directory) {
try {
Set-PSDebug -Trace 2
$files = Get-ChildItem $directory -Filter "*.txt"
Write-Output "Found $($files.Count) files"
foreach ($file in $files) {
$content = Get-Content $file.FullName
# 何らかの処理
$processed = $content -replace "old", "new"
Set-Content $file.FullName $processed
}
} finally {
Set-PSDebug -Off
}
}
Web API呼び出しのデバッグ
function Call-WebAPI($url, $params) {
# APIパラメータの確認
Set-PSDebug -Trace 2
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}
$response = Invoke-RestMethod -Uri $url -Method POST -Headers $headers -Body ($params | ConvertTo-Json)
Set-PSDebug -Off
return $response
}
データ変換処理のデバッグ
# CSVデータの変換処理
$csv_data = Import-Csv "data.csv"
Set-PSDebug -Trace 2
$transformed = $csv_data | ForEach-Object {
[PSCustomObject]@{
FullName = "$($_.FirstName) $($_.LastName)"
Age = [int]$_.Age
Department = $_.Dept.ToUpper()
}
}
Set-PSDebug -Off
$transformed | Export-Csv "transformed.csv" -NoTypeInformation
トラブルシューティングのベストプラクティス
1. エラーメッセージと組み合わせる
try {
# 通常実行
.\my_script.ps1
} catch {
Write-Output "エラーが発生しました:"
Write-Output "Line: $($_.InvocationInfo.ScriptLineNumber)"
Write-Output "Message: $($_.Exception.Message)"
# エラー箇所をデバッグ実行
Write-Output "`nデバッグモードで再実行します..."
Set-PSDebug -Trace 2 -Step
# 問題箇所のみ実行
Set-PSDebug -Off
}
2. ログ出力と組み合わせる
# デバッグ情報をログファイルに保存
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$log_file = "debug_$timestamp.log"
Set-PSDebug -Trace 2
.\my_script.ps1 *> $log_file 2>&1
Set-PSDebug -Off
Write-Output "デバッグログを保存しました: $log_file"
3. 他のデバッグ機能との使い分け
# Write-Debugとの組み合わせ
function My-Function($param) {
Write-Debug "Function started with param: $param"
# 複雑な処理の部分だけSet-PSDebugを使用
Set-PSDebug -Trace 2
$result = Complex-Processing $param
Set-PSDebug -Off
Write-Debug "Function completed with result: $result"
return $result
}
# 実行時
$DebugPreference = "Continue" # Write-Debugを有効化
My-Function "test_value"
コメント