Skip to content

Instantly share code, notes, and snippets.

@davidlu1001
Created July 23, 2024 02:13
Show Gist options
  • Save davidlu1001/c5ab26c7e8aa800a0cdb6ee9d8718120 to your computer and use it in GitHub Desktop.
Save davidlu1001/c5ab26c7e8aa800a0cdb6ee9d8718120 to your computer and use it in GitHub Desktop.
Get EventLog Summary with latest message
<#
.SYNOPSIS
Retrieves and summarizes Event Log data from local or remote machines.
.DESCRIPTION
This script retrieves Event Log data from specified machines, groups the events,
and provides a summary including count and the latest message for each group.
.PARAMETER ComputerName
Specifies the target computers. Default is the local machine.
.PARAMETER LogNames
Specifies the Event Log names to query. Default is "Application" and "System".
.PARAMETER ProviderNames
Specifies the Event Log provider names to filter. Supports multiple values and wildcards. Default is all providers (*).
.PARAMETER Levels
Specifies the Event Log levels to filter. Default is "Critical", "Error", and "Warning".
.PARAMETER DaysAgo
Specifies how many days ago to start the query. Default is 1 day.
.PARAMETER OutputFile
Specifies the file path for the CSV output. Default is "EventLogSummary.csv" in the current directory.
.EXAMPLE
.\Get-EventLogSummary.ps1 -ComputerName "Server1", "Server2" -LogNames "Application", "System" -ProviderNames "Microsoft-Windows-*", "Application Error" -Levels "Error", "Critical" -DaysAgo 7 -OutputFile "C:\Logs\Summary.csv"
.NOTES
Requires PowerShell 5.1 or later.
Ensure you have the necessary permissions on the remote computers.
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]$ComputerName = $env:COMPUTERNAME,
[Parameter()]
[string[]]$LogNames = @("Application", "System"),
[Parameter()]
[string[]]$ProviderNames = @("*"),
[Parameter()]
[ValidateSet("Critical", "Error", "Warning", "Information", "Verbose")]
[string[]]$Levels = @("Critical", "Error", "Warning"),
[Parameter()]
[int]$DaysAgo = 1,
[Parameter()]
[string]$OutputFile = "EventLogSummary.csv"
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
function Write-Log {
param (
[string]$Message,
[ValidateSet('Information', 'Warning', 'Error')]
[string]$Severity = 'Information'
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "[$timestamp] [$Severity] $Message"
Write-Verbose $logMessage
if ($Severity -eq 'Warning') {
Write-Warning $Message
} elseif ($Severity -eq 'Error') {
Write-Error $Message
}
}
function Get-EventLogSummaryInternal {
param(
[string[]]$LogNames,
[string[]]$ProviderNames,
[string[]]$Levels,
[datetime]$StartTime
)
$levelMap = @{
"Critical" = 1
"Error" = 2
"Warning" = 3
"Information" = 4
"Verbose" = 5
}
$events = foreach ($log in $LogNames) {
try {
$providerFilter = if ($ProviderNames -contains '*') {
""
} else {
"and (*[System[Provider[" + (($ProviderNames | ForEach-Object { "@Name='$_'" }) -join " or ") + "]]])"
}
$levelFilter = "and (*[System[" + (($Levels | ForEach-Object { "Level=" + $levelMap[$_] }) -join " or ") + "]])"
$filterXml = @"
<QueryList>
<Query Id="0" Path="$log">
<Select Path="$log">
*[System[TimeCreated[@SystemTime&gt;='$($StartTime.ToUniversalTime().ToString("o"))']]]
$providerFilter
$levelFilter
</Select>
</Query>
</QueryList>
"@
Write-Verbose "XML Filter for $log : $filterXml"
Get-WinEvent -FilterXml $filterXml -ErrorAction Stop
} catch [System.Diagnostics.Eventing.Reader.EventLogNotFoundException] {
Write-Warning "Log $log not found on $env:COMPUTERNAME. Skipping."
} catch {
Write-Warning "Failed to query log $log on $env:COMPUTERNAME. Error: $_"
}
}
$events | Group-Object Id, ProviderName, LogName, LevelDisplayName |
ForEach-Object {
$latestEvent = $_.Group | Sort-Object TimeCreated -Descending | Select-Object -First 1
[PSCustomObject]@{
Server = $env:COMPUTERNAME
EventId = $_.Group[0].Id
ProviderName = $_.Group[0].ProviderName
LogName = $_.Group[0].LogName
LevelDisplayName = $_.Group[0].LevelDisplayName
Count = $_.Count
LatestTime = $latestEvent.TimeCreated
LatestMessage = $latestEvent.Message -replace "`r`n|`r|`n", " "
}
} | Sort-Object Count -Descending
}
function Get-EventLogSummary {
param (
[string]$ComputerName,
[string[]]$LogNames,
[string[]]$ProviderNames,
[string[]]$Levels,
[datetime]$StartTime
)
Write-Log "Querying event logs on $ComputerName"
try {
if ($ComputerName -eq $env:COMPUTERNAME) {
# Local execution
Get-EventLogSummaryInternal -LogNames $LogNames -ProviderNames $ProviderNames -Levels $Levels -StartTime $StartTime
} else {
# Remote execution
Invoke-Command -ComputerName $ComputerName -ScriptBlock ${function:Get-EventLogSummaryInternal} -ArgumentList $LogNames, $ProviderNames, $Levels, $StartTime
}
} catch {
Write-Log "Failed to query event logs on $ComputerName. Error: $_" -Severity 'Error'
return $null
}
}
# Calculate StartTime from DaysAgo
$StartTime = (Get-Date).AddDays(-$DaysAgo)
# Main script execution
$allEvents = @()
foreach ($computer in $ComputerName) {
$computerEvents = Get-EventLogSummary -ComputerName $computer -LogNames $LogNames -ProviderNames $ProviderNames -Levels $Levels -StartTime $StartTime
if ($computerEvents) {
$allEvents += $computerEvents
}
}
if ($allEvents.Count -gt 0) {
Write-Log "Exporting results to $OutputFile"
try {
$allEvents | Export-Csv -Path $OutputFile -NoTypeInformation
Write-Log "Results exported successfully to $OutputFile"
} catch {
Write-Log "Failed to export results to $OutputFile. Error: $_" -Severity 'Error'
}
} else {
Write-Log "No events found matching the criteria" -Severity 'Warning'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment