LoginSignup
5
5

More than 5 years have passed since last update.

PowerShell でイベントログを JSON 出力する

Last updated at Posted at 2017-07-21

はじめに

PowerShell でイベントログを JSON 形式で出力するスクリプトの紹介です。
イベントログを収集して他のプログラムで読み込むことを想定して JSON 形式にしています。
本記事の構成は以下です。

  • 実行環境
  • イベントログを取得
  • イベントログのフィルタリング
  • 取得したイベントログを JSON 形式で出力
  • 補足情報

実行環境

  • Windows 10
  • .NET Framework 4.7
  • Windows PowerShell 5.0 (推奨 : 3.0 以上)

イベントログを取得

PowerShell でイベントログを取得し、コンソールに表示してみます。
イベントログの取得には、Get-WinEvent コマンドを使用します。1
なお、管理者権限で PowerShell を起動しないと、セキュリティのイベントログを取得出来ないので注意して下さい。

PS C:\powershell> Get-WinEvent -ListLog *

LogMode   MaximumSizeInBytes RecordCount LogName
-------   ------------------ ----------- -------
Circular            20971520       23091 Application
Circular            20971520           0 HardwareEvents
Circular            20971520       30119 Security
Circular            20971520       15717 System

# (中略)

Circular             1052672             Network Isolation Operational
Circular             1052672         188 Setup
Circular             1052672             Windows Networking Vpn Plugin Platform/Operational
Circular             1052672             Windows Networking Vpn Plugin Platform/OperationalVerbose

Get-WinEvent コマンドでイベントログを取得できる事を確認できました。
しかし、出力結果の通り全イベントログが出力されているため、欲しい情報へのアクセス性がよくありません。
次に、イベントログから任意の情報のみをフィルタリングして取得する方法を紹介します。

イベントログのフィルタリング

Get-WinEvent で取得するイベントログにフィルタをかけたい場合は、-FilterHashtable オプションを使います。
-FilterHashtable オプションでは、連想配列 @{} を用いてフィルタ条件を指定します。

例として、以下のスクリプトにて取得するイベントログの種類レベルをフィルタリングしてみます。

GetFilteredEventLog.ps1
# (1) ログの種類を指定
$logName = "Security", "System", "Application"

# (2) ログレベルを指定 (1:Critical, 2:Error, 3:Warning)
$eventLevel = 1, 2, 3  

# (3) (1) と (2) の条件でイベントログ取得のフィルタを作成
$filter = @{}
$filter.Add("LogName", $logName)
$filter.Add("Level", $eventLevel )
$filter.Add("StartTime", (Get-Date).AddHours(-24))
$filter.Add("EndTime", (Get-Date))

# (4) イベントログを取得
$eventLogs = Get-WinEvent -FilterHashtable $filter

それでは早速、GetFilteredEventLog.ps1 を実行してみます。
.ps1 ファイルを PowerShell で実行するためには ExecutionPolicyRemoteSigned に設定しなければなりません。

しかし、ExecutionPolicy の設定変更の影響はシステムワイドなので、本記事では、PowerShell 実行時に -ExecutionPolicy オプションをつけることで一時的に RemoteSigned に設定します。

PS C:\powershell> PowerShell -ExecutionPolicy RemoteSigned .\GetFilteredEventLog.ps1

   ProviderName: Microsoft-Windows-DistributedCOM

TimeCreated                     Id LevelDisplayName Message
-----------                     -- ---------------- -------
2017/07/24 19:53:43          10016 エラー           アプリケーション固有 のアクセス許可の設定では、CLSID ...
2017/07/24 12:00:44          10016 エラー           アプリケーション固有 のアクセス許可の設定では、CLSID ...

   ProviderName: Microsoft-Windows-Kernel-Processor-Power

TimeCreated                     Id LevelDisplayName Message
-----------                     -- ---------------- -------
2017/07/24 15:54:51             37 警告             グループ 0 のプロセッサ 3 のスピードはシステム ファームウェアに...

フィルタに設定した通り、エラーと警告に関するイベントログを取得できました。
しかし、このままではログの可読性に欠けるので、JSON 形式で出力してみます。

取得したイベントログを JSON 形式で出力

JSON 形式で出力

JSON 形式での出力には、ConvertTo-Json コマンド を使用します。
(※) ConvertTo-Json は Windows PowerShell 3.0 以降でしか動作しません。

先程のスクリプトに、以下のコメント #(5) 以降を追記します。

GetFilteredEventLog.ps1
# ((1) ~ (3) 省略)

# (4) イベントログを取得
$eventLogs = Get-WinEvent -FilterHashtable $filter

# (これより下を追記)
# (5) イベントログを JSON 形式で出力
$eventLogs | ConvertTo-Json

同様に、追記した GetFilteredEventLog.ps1 を実行してみたいのですが、ここで 1 点問題があります。

それは、上記のスクリプトを実行すると Get-WinEvent コマンドで取得できるイベントログの全項目が出力されてしまうことです。
そこで、欲しい項目のみ出力できるようにイベントログをフィルタリングします。

任意の項目を抽出して JSON 形式で出力

任意の項目を抽出するには、Select-Object コマンドを利用します。

以下のスクリプトの通り、$queryItems のリストにイベントログから抽出したい項目だけを設定しておきます。(#(3'))2
そして、Get-WinEvent でイベントログを取得する際に、先に述べたフィルタ条件に加え Select-Object の処理を連結します。(#(4))

例として、イベントログから以下の項目を抽出してみます。

  • ID(id)
  • 種類(logName)
  • レベル(levelDisplayName)
  • イベントの発生時刻(datetime)
  • プロバイダ名(providerName)
  • メッセージ(message)
GetFilteredEventLog.ps1
# ((1) ~ (3) 省略)

# (3') イベントログから抽出したい必要な項目だけを設定
$queryItems = New-Object System.Collections.ArrayList
[void]$queryItems.Add(@{Name="id";Expression={$_.id}})
[void]$queryItems.Add(@{Name="logName";Expression={$_.LogName}})
[void]$queryItems.Add(@{Name="levelDisplayName";Expression={$_.LevelDisplayName}})
[void]$queryItems.Add(@{Name="datetime";Expression={$_.TimeCreated.datetime}})
[void]$queryItems.Add(@{Name="providerName";Expression={$_.ProviderName}})
[void]$queryItems.Add(@{Name="message";Expression={$_.Message}})

# (4) イベントログを取得
$eventLogs = Get-WinEvent -FilterHashtable $filter | Select-Object $queryItems

# (5) イベントログを JSON 形式で出力
$eventLogs  | ConvertTo-Json

それでは最後に、完成した GetFilteredEventLog.ps1 を実行してみましょう。

PS C:\powershell> PowerShell -ExecutionPolicy RemoteSigned .\GetFilteredEventLog.ps1
[
    {
        "id":  10016,
        "logName":  "System",
        "levelDisplayName":  "エラー",
        "datetime":  "2017年7月24日 19:53:43",
        "providerName":  "Microsoft-Windows-DistributedCOM",
        "message":  "アプリケーション固有 のアクセス許可の設定では、CLSID \r\n{D63B10C5-BB46-4990-A94F-E40B9D520160}\r\n および APPID \r\n{9CA88EE3-ACB7-47C8-AFC4-AB702511C276}\r\n の COM サーバー アプリケーションに対するローカルアクティブ化のアクセス許可を、アプリケーション コンテナー 利用不可 SID (利用不可) で実行中のアドレス LocalHost (LRPC 使用) のユーザー NT AUTHORITY\\SYSTEM SID (S-1-5-18) に与えることはできません。このセキュリティ アクセス許可は、コンポーネント サービス管理ツールを使って変更できます。"
    },
    {
        "id":  37,
        "logName":  "System",
        "levelDisplayName":  "警告",
        "datetime":  "2017年7月24日 15:54:51",
        "providerName":  "Microsoft-Windows-Kernel-Processor-Power",
        "message":  "グループ 0 のプロセッサ 3 のスピードはシステム ファームウェアによって制限されます。プロセッサは、最後のレポート後 602804 秒間このパフォーマンスが制限された状態にあります。"
    },
    {
        "id":  10016,
        "logName":  "System",
        "levelDisplayName":  "エラー",
        "datetime":  "2017年7月24日 12:00:44",
        "providerName":  "Microsoft-Windows-DistributedCOM",
        "message":  "アプリケーション固有 のアクセス許可の設定では、CLSID \r\n{D63B10C5-BB46-4990-A94F-E40B9D520160}\r\n および APPID \r\n{9CA88EE3-ACB7-47C8-AFC4-AB702511C276}\r\n の COM サーバー アプリケーションに対するローカルアクティブ化のアクセス許可を、アプリケーション コンテナー 利用不可 SID (利用不可) で実行中のアドレス LocalHost (LRPC 使用) のユーザー NT AUTHORITY\\SYSTEM SID (S-1-5-18) に与えることはできません。このセキュリティ アクセス許可は、コンポーネント サービス管理ツールを使って変更できます。"
    }
]

$queryItems で設定した項目だけが抽出されて JSON 形式でイベントログが出力出来ました。

おわりに

今回は以下の 3 つを紹介しました。

  • イベントログを取得
  • イベントログのフィルタリング
  • 取得したイベントログを JSON 形式で出力

今後は、JSON 形式で出力したイベントログを他のプログラムで読み込み、定期的にイベントログを取得してレポートを表示する仕組みを整えてみようと思います。

補足情報

フィルタで設定したログレベル値の対応関係を補足しておきます。

ログレベルと値の対応関係は、Windows のイベントビューアーの 現在のログをフィルター から確認することが出来ます。

例として、ログレベル "情報" のみを選択してみます。
フィルタ条件_Qiita.PNG

XMLタブの Query 内を確認すると、 "Level = 4 or Level = 0" と記載があります。
これより、情報レベルのイベントログを PowerShell から取得したい場合は、上記スクリプトの $eventLevel0, 4 を設定すれば良いです。


参考


  1. PowerShell でイベントログを取得するコマンドには、Get-EventLog もありますが、 Windows Vista / Windows Server 2008 以降のイベントログの新形式に対応していないとのことで使用を避けました。 

  2. ここでは、POJO に格納しやすいように敢えて各項目名の頭文字を小文字に設定しています。 

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5