動くコード図鑑技術記事現場の渡り方キャリア論すべての記事About
技術記事

PowerShell で Windows イベントログを監視して特定エラーをメール通知する — 1人運用の業務SE向け自動化

バイブス父さん
現役の業務SE
2026年7月5日11 min read
PowerShell で Windows イベントログを監視して特定エラーをメール通知する — 1人運用の業務SE向け自動化

みなさんこんにちは!ヒロポンです!

サーバーのイベントログ、毎朝目視で見てませんか??

俺もそうでした。流通系の基幹システムの保守をやってた頃、朝イチでサーバーにリモート接続して、イベントビューア開いて、赤いエラーが出てないか目で追う。これを毎日。

で、ある朝。前夜にサービスが落ちてたのを半日気付かなかった。目視って、見落とすんですよ。人間だもん。

これ、PowerShell イベントログ 監視を組めば自動化できます。エラーが出たら勝手にメールが飛んでくる。朝の目視チェックがまるごと消える。

この記事では、Get-WinEvent で対象エラーを絞って、Send-MailMessage で通知して、タスクスケジューラで定期実行するところまで、1人運用の業務SEが組める手順で書いていきます。

この記事でできること(完成イメージ)

組み上がると、こういう流れが10分おきに勝手に回ります。

イベントログ監視の自動化フロー。タスクスケジューラが定期起動し、Get-WinEvent で直近N分のログを取得、対象エラーがあればメール通知、なければ何もせず終了する

ゴールは「エラーが出た時だけメールが来る」状態。平常時は何も鳴らない。だからメールが来た=何か起きた、と即わかります。

前提条件・必要なもの

  • Windows Server(クライアント Windows でも可)
  • PowerShell 5.1(Windows 標準。この記事は 5.1 前提で書きます)
  • 送信できる SMTP サーバー(社内のメールサーバー等)
  • スクリプトを置くフォルダ(例: C:\scripts\

PowerShell 7 を使ってる人向けの注意は、後ろのトラブルシューティングで1つ触れます。

この記事のコードは Windows 専用 cmdlet(Get-WinEvent / タスクスケジューラ系 / Send-MailMessage)が中心です。構文は検証済みですが、実行は Windows + PowerShell 5.1 環境でやってください。

Step 1: Get-WinEvent で対象ログのエラーを絞る

まずはイベントログから「直近のエラーだけ」を取り出す。使うのは Get-WinEventFilterHashtable です。

# System ログから直近10分の Error を取得
$since = (Get-Date).AddMinutes(-10)

$events = Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    Level     = 2          # 1=Critical, 2=Error, 3=Warning, 4=Information
    StartTime = $since
} -ErrorAction SilentlyContinue

Level = 2 が Error。StartTime で「直近10分」に絞ってます。

地味だけど重要なのが -ErrorAction SilentlyContinueGet-WinEvent該当ログが0件だとエラーを吐く仕様なんですよ。だからこれを付けないと「エラーが無いのにスクリプトがコケる」っていう、なんとも変な動きになります。

古い Get-EventLog でも似たことはできるんですが、新しいログ(セットアップログや一部のアプリログ)を拾えない場面があって、今は Get-WinEvent が定番です。

Step 2: 拾う条件を組み立てる(Level / EventID / 直近N分)

「全部の Error」だと、現場によっては多すぎる。そういう時は EventID で絞ります

# 特定の EventID だけ拾う
# (例: 7=ディスクのコントローラエラー, 7034=サービスが予期せず終了)
$events = Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    Level     = 2
    Id        = 7, 7034
    StartTime = $since
} -ErrorAction SilentlyContinue

Id = 7, 7034 みたいにカンマで複数指定できます。自分の現場で「これは絶対拾いたい」EventID を、ここに足していく感じ。

LogName'Application' にすればアプリケーションログ、'Security' ならセキュリティログも見られます。こんな感じで、監視したいログと条件を組み合わせていきます。

Step 3: 引っかかったらメールで通知する(Send-MailMessage)

対象イベントがあったら、メールを飛ばす。

if ($events) {
    # 本文を読みやすく整形
    $body = $events |
        Select-Object TimeCreated, Id, LevelDisplayName, Message |
        Format-List | Out-String

    Send-MailMessage `
        -From       'monitor@example.co.jp' `
        -To         'admin@example.co.jp' `
        -Subject    "[警告] $($env:COMPUTERNAME) でエラー $($events.Count) 件" `
        -Body       $body `
        -SmtpServer 'smtp.example.co.jp'
}

if ($events) で「1件でもあれば」通知。$events.Count で件数、$env:COMPUTERNAME でどのサーバーかを件名に突っ込んでおくと、メールを見た瞬間に状況がつかめます。

平常時は $events が空なので、if に入らず何も送りません。いい感じに「異常時だけ鳴る」が実現します。

⚠️ Send-MailMessagePowerShell 7 で非推奨(obsolete)になっています。5.1 ではそのまま使えますが、7 や新規構築なら MailKit などの代替を検討してください(詳細はトラブルシューティングに)。

Step 4: タスクスケジューラで定期実行する

ここまでを1つの .ps1(例: C:\scripts\EventMonitor.ps1)にまとめたら、タスクスケジューラで10分おきに回します。

# 監視スクリプトを10分ごとに実行するタスクを登録
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
    -Argument '-NoProfile -ExecutionPolicy Bypass -File "C:\scripts\EventMonitor.ps1"'

$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) `
    -RepetitionInterval (New-TimeSpan -Minutes 10)

Register-ScheduledTask -TaskName 'EventLogMonitor' `
    -Action $action -Trigger $trigger `
    -User 'SYSTEM' -RunLevel Highest

-User 'SYSTEM' で実行アカウントを指定、-RunLevel Highest で管理者権限で動かす。ここの権限設定が後でじわっと効いてくるので、覚えておいてください。

動作確認

組んだら、本番を待たずにわざとエラーを起こして確認します。

# テスト用に Application ログへ Error を1件書き込む
New-EventLog -LogName Application -Source 'MonitorTest' -ErrorAction SilentlyContinue
Write-EventLog -LogName Application -Source 'MonitorTest' `
    -EntryType Error -EventId 9999 -Message 'テストエラーです'

このあと監視スクリプトを手で1回流して(または10分待って)、メールが届けばOK。届かなかったら、次のトラブルシューティングを見てください。

動作確認メモ: ここまでのコードは Windows + PowerShell 5.1 専用 cmdlet が中心のため、開発機の Linux / pwsh では構文検証までしか通せません(構文は全ブロック検証済み)。実機(Windows Server)での動作確認をおすすめします。

トラブルシューティング(こんなエラーが出たら)

Get-WinEvent で「No events were found」と出る

これ、エラーじゃなくて0件だっただけってことが多いです。Get-WinEvent は該当0件で例外を投げる仕様なので、Step 1 みたいに -ErrorAction SilentlyContinue を付けて握りつぶします。

ただし握りつぶしすぎると本当のエラーまで消える。-ErrorAction の扱いは PowerShell の ErrorAction で踏む3パターン も合わせて見ておくと安全です。

メールが飛ばない(Send-MailMessage が非推奨の件)

正直に言うと、俺もここで30分溶かしました。

Send-MailMessage は PowerShell 7 系で非推奨(obsolete)になっていて、Microsoft も「安全な接続を保証しない」として新規利用を推奨していません。5.1 では動きますが、7 で組むなら MailKit(NuGet)、Microsoft 365 環境なら Microsoft Graph 経由が今の定番です。

5.1 で動かない時は、SMTP サーバー側が認証や TLS を要求してるケースが多いので、-Credential-UseSsl を足して試してみてください。

タスクは動くのにメールが来ない(権限で空振り)

タスクスケジューラの実行アカウントにログの読み取り権限がないと、Get-WinEvent が空振りして何も拾えません。手で実行すると動くのにタスクだと鳴らない。ん?手だと動くのに??ってなる、典型パターンです。

Security ログを読むなら、特に権限が要ります。Step 4 の -User 'SYSTEM' で動かすか、ログ読み取り権限を持つアカウントを指定してください。

まとめ

要点はこれだけ。

  • 取得は Get-WinEvent -FilterHashtableLevel=2StartTime でエラーを直近N分に絞る
  • Get-WinEvent は0件で例外を吐くので -ErrorAction SilentlyContinue 必須
  • 通知は Send-MailMessage(5.1 はOK・7 は非推奨なので代替検討)
  • タスクスケジューラで定期実行。実行アカウントのログ読み取り権限に注意

監視を1回組んでおくだけで、朝の目視が消えて、夜中の事故にも気付ける。こんな感じで、1人運用ほど効きます!!

PowerShell の運用自動化まわりを体系的に押さえたいなら、スクリプト系の解説書を1冊持っておくと、この手の「どう組むのが定番か」を調べる時間がまるっと浮きます。

このスクリプト、C:\scripts\ に置いてそのまま回してください。

よくある質問

Q1. Get-EventLog と Get-WinEvent はどちらを使うべきですか?

新規に書くなら Get-WinEvent を推奨します。Get-EventLog は古い API で、Windows Vista 以降に追加されたログ(セットアップログや一部のアプリログ)を拾えない場合があります。Get-WinEventFilterHashtable でサーバー側フィルタが効くので、大量ログでも速いです。

Q2. 直近N分ではなく「前回実行以降」で拾えますか?

できます。前回実行時刻をファイルに保存しておき、次回その時刻を StartTime に渡す方式が定番です。ただし実装が増えるので、まずは「実行間隔と同じN分」で重複なく拾える設計(10分間隔なら直近10分)から始めるのがシンプルです。

Q3. メール以外(Teams / Slack)に通知できますか?

できます。Send-MailMessage の部分を、各サービスの Webhook(Incoming Webhook)に Invoke-RestMethod で POST する形に差し替えるだけです。通知先がチャットなら、その場で気付けるので1人運用との相性は良いです。

Q4. PowerShell 7 でこのスクリプトは動きますか?

Get-WinEvent とタスクスケジューラ系は 7 でも動きます。問題は Send-MailMessage だけで、7 では非推奨です。7 で組むなら通知部分を MailKit か Webhook に置き換えれば、残りはそのまま使えます。

次に読むべき記事

以上!

同じ目視チェックで疲れてる人いたら、どんどんシェア待ってるぜ!!


執筆者

バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SIer の正社員からフリーランスに転じ、 複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る

この記事のコードと手順は ぜんぶ動作検証済み。 安心して現場で試してくれ。
バイブス父さん

現役の業務SE。C# / SQL Server 保守の現場から、コードも人もキャリアも全部書く。 実体験ベース。

運営者について