【Powershell】WindowsイベントログをCSVに出力するツール(進捗状況表示つき)

スポンサーリンク
powershell

Windowsイベントログが全量CSVに出力されるツールを作りたい

仕事でWindowsイベントログをCSVに保存しようとしたら何故か350レコードぐらいしか出力されない、というバグに遭遇したので作成。
でも家のPCなら普通に全量出力できた。カナシミ。
そのうち他のスクリプトみたいにリモートサーバにできるようにしよう。

搭載機能

  • ローカルのWindowsイベントログをCSVへ出力する。ファイル名に実行年月日時分秒をつける。
  • プルダウンで対象イベントログ名とレベル(情報、警告、エラー、重大)を選択できるようにする。
  • イベントログ状況によっては出力に時間かかるので、進捗状況が表示されるようにする。
  • 後からエラーなどを終えるように実行ログを別ファイルとして吐き出す。※別途関数にしたほうが良かった気がする。要改善

コード

絶対改善余地があるけどこんな感じ。

#
# Windowsサーバのイベントログから情報をCSVに出力するスクリプト
#
# ファイル名:WinEventLogToCSV.ps1


# CSVテーブルの用意
$CSVdatas = @()

# 日付の取得
$date = Get-Date -Format "yyyyMMdd";

# 時間の取得
$time = Get-Date -Format "HHmmss";

# 調査結果を出力するフォルダ
$scriptPath = $MyInvocation.MyCommand.Path
$scriptPath_split = Split-Path -Parent $scriptPath
$ResultFolder = ($scriptPath_split+"\結果")

# 調査結果出力結果フォルダがなかったら作成
if( -not (Test-Path $ResultFolder) ) {
    New-Item $ResultFolder -Type Directory
}

# 実行結果出力ファイル名
$ExecuteLogFile = ( "\ExecuteLog_"+$date+"_"+$time+".log" )

#実行結果出力フォルダとファイル名のマージ
$ExecuteLog = Join-Path $ResultFolder $ExecuteLogFile

# アセンブリのロード
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# フォーム全体の設定
$form = New-Object System.Windows.Forms.Form
$form.Text = "イベントログ取得ツール"
$form.Size = New-Object System.Drawing.Size(450,200)
$form.StartPosition = "CenterScreen"
$form.font = $Font

# ラベルを表示
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,10)
$label.Size = New-Object System.Drawing.Size(270,20)
$label.Text = "取得したいイベントログの情報を選択してください。"
$form.Controls.Add($label)

# LogNameラベルを表示
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(50,35)
$label.Size = New-Object System.Drawing.Size(100,10)
$label.Text = "LogName"
$form.Controls.Add($label)

# Levelラベルを表示
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(250,35)
$label.Size = New-Object System.Drawing.Size(100,10)
$label.Text = "LogLevel"
$form.Controls.Add($label)

# OKボタンの設定
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(250,100)
$OKButton.Size = New-Object System.Drawing.Size(75,30)
$OKButton.Text = "OK"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

# キャンセルボタンの設定
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(330,100)
$CancelButton.Size = New-Object System.Drawing.Size(75,30)
$CancelButton.Text = "Cancel"
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

# LogName用コンボボックスを作成
$Combo1 = New-Object System.Windows.Forms.Combobox
$Combo1.Location = New-Object System.Drawing.Point(50,50)
$Combo1.size = New-Object System.Drawing.Size(150,30)
$Combo1.DropDownStyle = "DropDown"
$Combo1.FlatStyle = "standard"
$Combo1.font = $Font
$Combo1.BackColor = "#005050"
$Combo1.ForeColor = "white"

# LogName用コンボボックスに項目を追加
[void] $Combo1.Items.Add("Application")
[void] $Combo1.Items.Add("security")
[void] $Combo1.Items.Add("setup")
[void] $Combo1.Items.Add("system")

# レベル選択用コンボボックスを作成
$Combo2 = New-Object System.Windows.Forms.Combobox
$Combo2.Location = New-Object System.Drawing.Point(250,50)
$Combo2.size = New-Object System.Drawing.Size(150,30)
$Combo2.DropDownStyle = "DropDown"
$Combo2.FlatStyle = "standard"
$Combo2.font = $Font
$Combo2.BackColor = "#005050"
$Combo2.ForeColor = "white"

# レベル選択用コンボボックスに項目を追加
[void] $Combo2.Items.Add("全部")
[void] $Combo2.Items.Add("情報")
[void] $Combo2.Items.Add("警告")
[void] $Combo2.Items.Add("エラー")
[void] $Combo2.Items.Add("重大")
[void] $Combo2.Items.Add("情報以外")

# フォームにコンボボックスを追加
$form.Controls.Add($Combo1)
$form.Controls.Add($Combo2)

# フォームを最前面に表示
$form.Topmost = $True

# フォームを表示+選択結果を変数に格納
$FormResult = $form.ShowDialog()

Start-Transcript $ExecuteLog

# 選択後、OKボタンが押された場合、選択項目を表示
if ($FormResult -eq "OK")
{
    $TargetLogName = $combo1.Text
   

    # 調査結果出力ファイル名
    $ResultFile = ( "\WinEventLog"+"_"+$date+"_"+$time+".csv" )

    # 調査結果出力フォルダとファイル名のマージ
    $Result = Join-Path $ResultFolder $ResultFile

    # レベル「全部」を正規表現に変換
    if ($combo2.Text -eq "全部") { $TargetLevel = ".*" } else {  $TargetLevel = $combo2.Text }

    # 指定イベントログを取得し、日付と時刻、イベントID、レベル、メッセージを表示する
    if ( $TargetLevel -eq "情報以外" ) {
    $Item = Get-WinEvent -Logname $TargetLogName | Where-Object { $_.LevelDisplayName -ne "情報" } | Select-Object -Property TimeCreated,Id,LevelDisplayName,Message
    } else {
    $Item = Get-WinEvent -Logname $TargetLogName | Where-Object { $_.LevelDisplayName -match $TargetLevel } | Select-Object -Property TimeCreated,Id,LevelDisplayName,Message
    }
    $LogCount = $Item.Length
    $counter   = 0
    $denominator = "/"+[string]$LogCount

    #取得したイベントログをCSVテーブルに格納する
    ForEach($b in $Item){
    $counter ++;
    Write-Progress -activity "進捗状況" -status $counter$denominator -percentComplete ($counter / $LogCount * 100)
    $CSVdata = New-Object PSObject | Select-Object TimeCreated,Id,LevelDisplayName,Message
    $CSVdata.TimeCreated = $b.TimeCreated
    $CSVdata.Id = $b.Id
    $CSVdata.LevelDisplayName = $b.LevelDisplayName
    $CSVdata.Message = $b.Message

    $CSVdatas += $CSVdata
    
    }

#イベントログをCSVへ変換する
$CSVdatas | Export-Csv $Result -Encoding UTF8 -NoTypeInformation


# 調査結果ファイルを開く
Invoke-item $Result

}else{

echo "操作はキャンセルされました"

exit

}

Stop-Transcript

実行イメージ

注意点と補足

・PowerShellが実行可能な環境である必要があります。
・共有フォルダなどで利用する場合は認証済みである必要があります。

改版履歴

2020/09/13 初版公開

コメント

タイトルとURLをコピーしました