Windows10のイベントログを取得してソートしてループ処理するPowerShell


各種イベントログを取得して時系列にソートを掛けたい要件があったので、サンプルを作った。

今回はSystemログを2回取得して配列A・Bに格納しているが、
イベントログのデータ構造は、ApplicationログもSecurityログも同じ(記事の下の付録参照)。
よって、別々の種類のイベントログであってもシンプルに配列を結合することで実現が可能。

PowerShellは配列同士の"＋"演算で配列の結合ができるため実装が大変シンプルになる。
(同じデータ構造を持ってくれているおかげで余計にデータを捏ねる必要がなくなって好都合だ)

以下のスクリプトは$todayの日付以降の最新のログを10件取得する仕様になっている。

```powershell:sortedArrayEventLog.ps1
$today = Get-Date -Format "yyyy年MM月dd日"
$lognum = 10

# 結合した配列を作るための配列A
$Events_A = Get-EventLog -LogName System -After $today -Newest $lognum

# 結合した配列を作るための配列B
$Events_B = Get-EventLog -LogName System -After $today -Newest $lognum

# 配列同士を結合して新しい配列を作る
$Events_Set = $Events_A + $Events_B

# イベントログの発生時刻で降順にソートして、一つ一つループ処理する
$Events_Set.GetEnumerator() | Sort-Object -Property TimeGenerated -Descending | ForEach-Object {
    Write-Host $_.InstanceId
}
```

バッチファイルを叩いて起動する

```powershell:sortedArrayEventLog.bat
set TODAY=%DATE:/=%
set PATH=%C:fuga%
set LOGPATH=%C:hoge%

echo %DATE% %TIME% >> %LOGPATH%\sortedArrayEventLog_bat_%TODAY%.log

powershell -ExecutionPolicy RemoteSigned -File %PATH%sortedArrayEventLog.ps1 -verb runas >> %LOGPATH%\sortedArrayEventLog_bat_%TODAY%.log

pause
```

##付録

なお、イベントログのデータ構造は以下の通り。
EventLogのデータ構造が同じであると示したいだけなのだが…ちょっとくどい。

* システムログのデータ構造

```powershell:EventLog_System
$today = Get-Date -Format "yyyy年MM月dd日"
PS > Get-EventLog -LogName System -After $today -Newest 1 |  Get-Member -MemberType Properties

   TypeName: System.Diagnostics.EventLogEntry#System/Microsoft-Windows-Kernel-Processor-Power/37

Name               MemberType     Definition
----               ----------     ----------
Category           Property       string Category {get;}
CategoryNumber     Property       int16 CategoryNumber {get;}
Container          Property       System.ComponentModel.IContainer Container {get;}
Data               Property       byte[] Data {get;}
EntryType          Property       System.Diagnostics.EventLogEntryType EntryType {get;}
Index              Property       int Index {get;}
InstanceId         Property       long InstanceId {get;}
MachineName        Property       string MachineName {get;}
Message            Property       string Message {get;}
ReplacementStrings Property       string[] ReplacementStrings {get;}
Site               Property       System.ComponentModel.ISite Site {get;set;}
Source             Property       string Source {get;}
TimeGenerated      Property       datetime TimeGenerated {get;}
TimeWritten        Property       datetime TimeWritten {get;}
UserName           Property       string UserName {get;}
EventID            ScriptProperty System.Object EventID {get=$this.get_EventID() -band 0xFFFF;}
```

* アプリケーションログのデータ構造

```powershell:EventLog_Application
PS > Get-EventLog -LogName Application -After $today -Newest 1 |  Get-Member -MemberType Properties


   TypeName: System.Diagnostics.EventLogEntry#Application/VSS/8224

Name               MemberType     Definition
----               ----------     ----------
Category           Property       string Category {get;}
CategoryNumber     Property       int16 CategoryNumber {get;}
Container          Property       System.ComponentModel.IContainer Container {get;}
Data               Property       byte[] Data {get;}
EntryType          Property       System.Diagnostics.EventLogEntryType EntryType {get;}
Index              Property       int Index {get;}
InstanceId         Property       long InstanceId {get;}
MachineName        Property       string MachineName {get;}
Message            Property       string Message {get;}
ReplacementStrings Property       string[] ReplacementStrings {get;}
Site               Property       System.ComponentModel.ISite Site {get;set;}
Source             Property       string Source {get;}
TimeGenerated      Property       datetime TimeGenerated {get;}
TimeWritten        Property       datetime TimeWritten {get;}
UserName           Property       string UserName {get;}
EventID            ScriptProperty System.Object EventID {get=$this.get_EventID() -band 0xFFFF;}
```

* セキュリティログのデータ構造

```powershell:EventLog_Security
PS > Get-EventLog -LogName Security -After $today -Newest 1 |  Get-Member -MemberType Properties


   TypeName: System.Diagnostics.EventLogEntry#Security/Microsoft-Windows-Security-Auditing/5379

Name               MemberType     Definition
----               ----------     ----------
Category           Property       string Category {get;}
CategoryNumber     Property       int16 CategoryNumber {get;}
Container          Property       System.ComponentModel.IContainer Container {get;}
Data               Property       byte[] Data {get;}
EntryType          Property       System.Diagnostics.EventLogEntryType EntryType {get;}
Index              Property       int Index {get;}
InstanceId         Property       long InstanceId {get;}
MachineName        Property       string MachineName {get;}
Message            Property       string Message {get;}
ReplacementStrings Property       string[] ReplacementStrings {get;}
Site               Property       System.ComponentModel.ISite Site {get;set;}
Source             Property       string Source {get;}
TimeGenerated      Property       datetime TimeGenerated {get;}
TimeWritten        Property       datetime TimeWritten {get;}
UserName           Property       string UserName {get;}
EventID            ScriptProperty System.Object EventID {get=$this.get_EventID() -band 0xFFFF;}
```