スクリプトを一度書いたら、同じ仕事を、何度でも任せられます。「先月の PC の台帳、どこにあったっけ? あの Excel、誰が最後に更新したの?」
情シスあるあるです。調べた結果が、手作業のコピペで Excel に入っていると、次に誰かが調べるとき、また最初からになります。
シリーズ「情シスのための PowerShell 入門」も、いよいよ最終回です。前回(第4回:スクリプト入門と実行ポリシー)で、スクリプトを作って動かせるようになりました。今回は、調査結果を CSV に出力し、ログを残し、エラーにも備える、小さな実用スクリプトを完成させます。
結論:「記録」と「備え」があれば、スクリプトは仕事道具になる
画面に出して終わりのスクリプトは、一回きりの使い捨てです。次の3つを足すと、道具になります。
| 足すもの | 使うコマンド | 効果 |
|---|---|---|
| 結果の保存 | Export-Csv |
調査結果を、あとから開ける・共有できる |
| 実行の記録 | Add-Content と Get-Date |
いつ・何をしたかが残る |
| エラーへの備え | try / catch と -ErrorAction Stop |
失敗しても、原因が記録される |
エラーを捕まえる:try / catch の落とし穴
PowerShell のエラーには、止まるエラーと、止まらないエラーがあります。try / catch で捕まえられるのは、止まるエラーだけです。
try { Get-Content .\nothing.txt } catch { 'caught' }
try { Get-Content .\nothing.txt -ErrorAction Stop } catch { '捕まえた: ' + $_.Exception.Message }

1つ目は、catch に入りませんでした。赤いエラーは出るのに、'caught' は表示されません。 2つ目は、-ErrorAction Stop を付けたので、catch に入り、エラーの内容を取り出せています。
-ErrorAction Stop を付けると、止まらないエラーが、止まるエラー(try / catch で捕まえられるもの)に格上げされます。try / catch を書くなら、中のコマンドに -ErrorAction Stop を付ける、これをセットで覚えておきます。スクリプトの先頭に $ErrorActionPreference = 'Stop' と書くと、全部のコマンドに、まとめて効かせられます。
$_.Exception.Message は、catch の中で、エラーの説明文を取り出す書き方です。
日時とログ
Get-Date -Format 'yyyyMMdd' # 20261010 のような日付(ファイル名に使う)
Get-Date -Format 'yyyy-MM-dd HH:mm:ss' # ログ用の時刻
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') 開始" | Add-Content -Path .\run.log -Encoding UTF8
Add-Content は、ファイルの末尾に追記します。ログの基本形は、「時刻+メッセージ」を1行ずつ足すだけです。ファイル名に日付を入れておくと、日ごとに分かれて、あとから探しやすくなります。
CSV 出力のコツ(5.1 と 7 の違い)
$info | Export-Csv -Path .\pc-info.csv -NoTypeInformation -Encoding UTF8
僕の環境で確かめた、Windows PowerShell 5.1 の注意点です。
-NoTypeInformationを付けないと、1行目に#TYPE ...という余計な行が入ります(5.1 の場合。PowerShell 7 では、付けなくても入りません)。-Encoding UTF8を付けると、BOM 付きの UTF-8 で保存されます(5.1 の場合)。日本語の列名が入っていても、Excel で開くときに、文字化けしにくくなります。PowerShell 7 の UTF8 は BOM なしなので、環境によっては、Excel で化けることがあります。
「どっちのバージョンで動かすか」で、出力が変わるので、CSV を共有するスクリプトは、動かす環境を決めておくのが安全です。
完成:PC の基本情報とサービスを CSV に出すスクリプト
# PC の基本情報と、動いているサービスを CSV に出力する
$ErrorActionPreference = 'Stop'
$today = Get-Date -Format 'yyyyMMdd'
$log = "C:\Temp\lab\pc-report_$today.log"
function Write-Log([string]$Message) {
"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" | Add-Content -Path $log -Encoding UTF8
}
try {
Write-Log '開始'
$os = Get-CimInstance -ClassName Win32_OperatingSystem
$info = [pscustomobject]@{
取得日時 = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
OS = $os.Caption
バージョン = $os.Version
最終起動 = $os.LastBootUpTime.ToString('yyyy-MM-dd HH:mm')
}
$info | Export-Csv -Path "C:\Temp\lab\pc-info_$today.csv" -NoTypeInformation -Encoding UTF8
$svc = Get-Service | Where-Object Status -eq 'Running' | Select-Object Name, DisplayName, Status
$svc | Export-Csv -Path "C:\Temp\lab\services_$today.csv" -NoTypeInformation -Encoding UTF8
Write-Log "サービス $($svc.Count) 件を出力しました"
} catch {
Write-Log "エラー: $($_.Exception.Message)"
throw
}
読み方は、こうです。
- 先頭で
$ErrorActionPreference = 'Stop'(どのエラーも、止まるエラーにする) Write-Logという小さな関数で、ログに時刻つきで追記するtryの中で、OS の情報(Get-CimInstance)と、動いているサービスを集めて、CSV に出すcatchで、エラーの内容をログに残し、throwで、もう一度エラーとして表に出す(握りつぶさない)
Get-CimInstance は、PowerShell 7 でも使えます。古い Get-WmiObject は 7 にないので、こちらを使うのが、あとあと楽です。
フォルダーのパス(C:\Temp\lab)は、例です。実際は、スクリプトの先頭の変数に出して、1か所で変えられるようにしておくと、使い回しが楽になります。
実行すると、こうなります。
.\pc-report.ps1

CSV が2つ(PC の情報とサービス一覧)、ログが1つできました。ログには、開始と、サービスを出力した件数が、時刻つきで残っています。Import-Csv で読み直すと、OS の名前(Windows 11 Pro)とバージョンが、取り出せています。第4回で触れた日本語の列名(バージョン)も、BOM 付きで保存したので、文字化けしていません。
本番で消す・止めるときは、-WhatIf を忘れない
このスクリプトは「見るだけ」ですが、運用では、ファイルを消したり、サービスを止めたりする処理も出てきます。そのときは、-WhatIf を付けて、予行演習を。付けられるコマンドでは、実行せずに、何が起きるかだけが表示されます(第2回のとおりです)。-Confirm を付けると、1件ずつ、確認を求められます。
僕のやらかし:変数が空だった日
古いログを消すスクリプトを書いたときのことです。こんな感じでした。
Remove-Item "$logDir\*" -Include *.log
$logDir に、フォルダーのパスを入れているつもりが、入力ミスで、変数が空でした。すると、"$logDir\*" は、\*、つまり、ドライブの直下を指してしまいます。
念のため、-WhatIf を付けて実行したら、画面に、ドライブ直下のファイル名が、ずらり。冷や汗が、ドッと出ました。-WhatIf を付けていなかったら、と思うと、今でも、おなかが痛くなります。
それ以来、消すコマンドの前には、いつも -WhatIf、そして、対象のパスを、画面に出して確認するクセがつきました。食べ放題で、お皿を下げる前に、「これ、まだ食べてる?」と聞くのと同じです。
全5回のまとめ:スクリプトで何ができるようになったか
| 回 | 学んだこと |
|---|---|
| ① | cmd との違い、動詞-名詞の命名規則、対比表 |
| ② | 基本コマンド10選、-WhatIf |
| ③ | パイプラインで、絞る・並べる・数える |
| ④ | スクリプト、実行ポリシー、文字コード |
| ⑤ | 実践:CSV 出力、ログ、try / catch |
次のステップ
PowerShell の基本が身についたら、次は、CSV を見る・加工する、そして、Active Directory、Microsoft 365、Entra ID、Intune の自動化へと進めます。このブログでも、続きを書いていきます。まずは、CSV を画面で並べ替え・絞り込みできる Out-GridView の記事を予定しています。
今回覚えたコマンド
| コマンド | 意味 |
|---|---|
try { } catch { } |
エラーを捕まえる |
-ErrorAction Stop |
止まらないエラーを、止まるエラーにする |
Get-Date -Format |
日時を、決まった形で出す |
Add-Content |
ファイルの末尾に追記する |
Export-Csv / Import-Csv |
CSV に書き出す / 読み込む |
Get-CimInstance |
OS やハードの情報を調べる |
-WhatIf / -Confirm |
予行演習 / 1件ずつ確認 |
参考
- about_CommonParameters(Microsoft Learn)
- about_Try_Catch_Finally(Microsoft Learn)
- Windows PowerShell 5.1 と PowerShell 7.x の違い(Microsoft Learn)
ITもごはんも、腹八分目が長続きのコツ!


コメント