end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

powershellで、windowsのイベントログから、pc操作ログを抽出する - 日毎出力

インターネット上の情報では、event idでのみ判定しているケースをよく見かけますが、 event id=1は、System time synchronized with the hardware clock.の場合も該当するようですので 抽出条件にsourceを加えています。

# windowsのeventログから、スリープやログオン等のイベントを抽出し
# 日毎のpc操作開始、終了を記録します。
# 出力対象のcsvファイルが既に存在する場合、マージします

$limitDate = -7
$folderPath = "c:/Users/end0t/tmp"
$fileName = "{0}_{1}_daily.csv" -f (Get-Date).ToString("yyyy"), $Env:USERNAME
$filePath = Join-Path -Path $folderPath -ChildPath $fileName

# 抽出対象のevent

$EventMsg = @{
    "Microsoft-Windows-Kernel-Power,42"         = "sleep on"
    "Microsoft-Windows-Kernel-Power,107"        = "sleep off"
    "Microsoft-Windows-Power-Troubleshooter,1"  = "sleep off"
    "Microsoft-Windows-Kernel-Power,506"        = "standby on"
    "Microsoft-Windows-Kernel-Power,507"        = "standby off"
    "Microsoft-Windows-Winlogon,7001"           = "windows login"
    "Microsoft-Windows-Winlogon,7002"           = "windows logout"
}

#出力対象のfolderがない場合、処理しません

if (!(Test-Path $folderPath)) {
    return
}

$events = Get-EventLog -LogName System `
  -After (Get-Date).AddDays($limitDate) | `
  Where-Object {
      $SrcAndId = $_.Source + ","+[String]$_.EventID
      $EventMsg.ContainsKey($SrcAndId) -eq $true }

$eventsPerDay = $events | Group-Object { $_.TimeGenerated.ToShortDateString() }

if (!(Test-Path $filePath)) {
    $eventsPerDay | ForEach-Object {
        $day = $_.Name
        $startEvent = ($_.Group | Select-Object -Last 1).TimeGenerated.ToString("HH:mm")
        $endEvent = ($_.Group | Select-Object -First 1).TimeGenerated.ToString("HH:mm")
        [PSCustomObject] @{
            "Date" = $day
            "FirstEventTime" = $startEvent
            "LastEventTime" = $endEvent
            "User" = $Env:USERNAME
            "ComputerName" = $Env:COMPUTERNAME
        }
    } | Sort-Object -Property Date | `
      Export-Csv -Path $filePath -Encoding Default -NoTypeInformation -Append
    return
}

# 既存csvと、今回抽出したeventに同一日のレコードがある場合
# 今回のレコードで上書き

$existingRecords = Import-Csv -Path $filePath

$eventsPerDay | ForEach-Object {
    $day = $_.Name
    $startEvent = ($_.Group | Select-Object -Last 1).TimeGenerated.ToString("HH:mm")
    $endEvent = ($_.Group | Select-Object -First 1).TimeGenerated.ToString("HH:mm")
    $newRecord = [PSCustomObject] @{
        "Date" = $day
        "FirstEventTime" = $startEvent
        "LastEventTime" = $endEvent
        "User" = $Env:USERNAME
        "ComputerName" = $Env:COMPUTERNAME
    }
    $existingRecord = $existingRecords | Where-Object { $_.Date -eq $day }
    if ($existingRecord) {
        $existingRecords = $existingRecords | Where-Object { $_.Date -ne $day }
        if ($existingRecord.FirstEventTime -lt $newRecord.FirstEventTime){
            $newRecord.FirstEventTime = $existingRecord.FirstEventTime
        }
    }
    $existingRecords += $newRecord
}

$existingRecords |  Sort-Object -Property Date | `
  Export-Csv -Path $filePath -Encoding Default -NoTypeInformation -Force

↑こう書くと、↓こう出力

"Date","First Event Time","Last Event Time","User","ComputerName"
"2023/04/14","00:29","12:23","end0t","LAPTOP-FSIBOAPD"
"2023/04/13","00:49","21:12","end0t","LAPTOP-FSIBOAPD"
"2023/04/12","00:42","23:19","end0t","LAPTOP-FSIBOAPD"
"2023/04/11","00:59","22:12","end0t","LAPTOP-FSIBOAPD"
"2023/04/10","00:59","22:55","end0t","LAPTOP-FSIBOAPD"
"2023/04/09","04:34","20:07","end0t","LAPTOP-FSIBOAPD"
"2023/04/08","00:51","20:05","end0t","LAPTOP-FSIBOAPD"
"2023/04/07","15:49","15:49","end0t","LAPTOP-FSIBOAPD"