Event Logs
Note
Query and filter Windows Event Logs with Get-WinEvent (modern) and Get-EventLog (legacy) to investigate errors, crashes, and system activity.
Overview
Windows records almost everything significant — service failures, logon attempts, application crashes, driver errors — into the Event Log. PowerShell gives you two ways in: Get-WinEvent, the modern, faster, and more flexible cmdlet that reads any log including the newer structured .evtx logs, and Get-EventLog, the older cmdlet limited to classic logs (Application, System, Security) but with a slightly simpler syntax. Use Get-WinEvent for new scripts; know Get-EventLog because you'll still see it in older code.
Basic Syntax
Get-WinEvent -LogName Application -MaxEvents 20
Get-WinEvent -FilterHashtable @{LogName='System'; Level=2}
Get-EventLog -LogName Application -Newest 20
Key Points
Get-WinEventworks on any event log, including application-specific and "Applications and Services Logs";Get-EventLogonly sees classic logs-FilterHashtableonGet-WinEventfilters at the source — much faster than piping toWhere-Object- Event
Level: 1=Critical, 2=Error, 3=Warning, 4=Information, 5=Verbose - Reading the Security log requires an elevated session
Listing Available Logs
# All logs on the system, with basic stats
Get-WinEvent -ListLog * | Select-Object LogName, RecordCount, IsEnabled
# Only logs that actually have events (avoids empty ones cluttering output)
Get-WinEvent -ListLog * | Where-Object { $_.RecordCount -gt 0 } |
Sort-Object RecordCount -Descending
Querying with Get-WinEvent
Basic Queries
# Most recent 20 events from the Application log
Get-WinEvent -LogName Application -MaxEvents 20
# Most recent errors only
Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2} -MaxEvents 20
# Events from the last 24 hours
Get-WinEvent -FilterHashtable @{
LogName = 'System'
StartTime = (Get-Date).AddHours(-24)
}
# Specific Event ID (e.g. 7034 = service crashed unexpectedly)
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7034}
Output:
TimeCreated ProviderName Id LevelDisplayName Message
----------- ------------ -- ---------------- -------
7/1/2026 8:42:15 AM Service Control Man… 7034 Error The Print Spooler service...
7/1/2026 8:12:03 AM Service Control Man… 7036 Information The Windows Update service...
Combining Filters
# Errors and warnings from a specific source, in the last 7 days
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Level = 2,3
StartTime = (Get-Date).AddDays(-7)
ProviderName = 'MyApplication'
}
# Query an "Applications and Services" log (needs the full path-style name)
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" -MaxEvents 50
-FilterHashtable Filters at the Source
# SLOW - reads every event, then filters in PowerShell
Get-WinEvent -LogName System -MaxEvents 5000 | Where-Object { $_.Id -eq 7034 }
# FAST - the Windows Event Log service does the filtering
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7034}
-FilterHashtable pushes the query down to the event log provider itself instead of pulling everything into PowerShell first. On a busy system this is the difference between a query that takes seconds versus minutes. Filtering by Message Content
# Text search across message bodies (slower - has to read and render each event)
Get-WinEvent -LogName Application -MaxEvents 500 |
Where-Object { $_.Message -like "*timeout*" }
# XPath filtering for more precise, faster queries
Get-WinEvent -LogName Application -FilterXPath "*[System[(EventID=1000)]]"
Querying with Get-EventLog (Legacy)
# Newest 20 entries
Get-EventLog -LogName Application -Newest 20
# Only errors
Get-EventLog -LogName Application -EntryType Error -Newest 20
# Filter by source
Get-EventLog -LogName System -Source "Service Control Manager" -Newest 20
# Events within a time range
Get-EventLog -LogName System -After (Get-Date).AddDays(-1)
Get-EventLog Is Deprecated
Get-EventLog is not available in PowerShell 7+ on non-Windows platforms and Microsoft recommends Get-WinEvent for all new scripts — it's faster, supports more logs, and is the actively maintained cmdlet. Get-EventLog still works in Windows PowerShell 5.1 and PowerShell 7 on Windows, but don't build new tooling around it.
Working with Event Details
# Pull specific properties out of events
Get-WinEvent -FilterHashtable @{LogName='System'; Id=7034} |
Select-Object TimeCreated, Id, LevelDisplayName, Message
# Access structured event data (XML) for events with custom properties
$event = Get-WinEvent -FilterHashtable @{LogName='System'; Id=7034} -MaxEvents 1
[xml]$xml = $event.ToXml()
$xml.Event.EventData.Data
# Export a set of events to CSV for further analysis
Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2} -MaxEvents 100 |
Select-Object TimeCreated, Id, ProviderName, Message |
Export-Csv -Path "C:\Reports\app-errors.csv" -NoTypeInformation
Remote Event Log Queries
# Query a remote computer's event log
Get-WinEvent -ComputerName "SERVER01" -LogName System -MaxEvents 20
# Query multiple servers and tag results with the source machine
$servers = @("SERVER01", "SERVER02")
foreach ($server in $servers) {
Get-WinEvent -ComputerName $server -FilterHashtable @{LogName='System'; Level=2} -MaxEvents 10 |
Select-Object @{N="Server";E={$server}}, TimeCreated, Id, Message
}
Important Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
-LogName | String | Which log to query | -LogName Application |
-FilterHashtable | Hashtable | Server-side filter (LogName, Id, Level, StartTime, etc.) | @{LogName='System'; Level=2} |
-MaxEvents | Int | Limit the number of results | -MaxEvents 20 |
-Id | Int[] | Get-EventLog: filter by Event ID (via Where-Object) | n/a for Get-EventLog directly |
-EntryType | String | Get-EventLog: Error, Warning, Information | -EntryType Error |
-ComputerName | String | Query a remote machine | -ComputerName "SRV01" |
-FilterXPath | String | Advanced XPath-based filtering | "*[System[(EventID=1000)]]" |
Common Patterns
# Pattern 1: Errors in the last N hours across two core logs
$since = (Get-Date).AddHours(-6)
@('Application', 'System') | ForEach-Object {
Get-WinEvent -FilterHashtable @{LogName=$_; Level=2; StartTime=$since} -ErrorAction SilentlyContinue
}
# Pattern 2: Count events by ID to spot noisy repeat errors
Get-WinEvent -LogName Application -MaxEvents 1000 |
Group-Object Id | Sort-Object Count -Descending | Select-Object -First 10 Count, Name
# Pattern 3: Daily error summary email body
$errors = Get-WinEvent -FilterHashtable @{LogName='Application'; Level=2; StartTime=(Get-Date).Date}
"$($errors.Count) errors logged today" | Out-String
Real-World Examples
Example: Daily Crash Report
Scenario: Every morning, summarize application crashes (Event ID 1000, .NET/native crash reporting) from the previous day into a report.
$yesterday = (Get-Date).Date.AddDays(-1)
$today = (Get-Date).Date
$crashes = Get-WinEvent -FilterHashtable @{
LogName = 'Application'
Id = 1000
StartTime = $yesterday
EndTime = $today
} -ErrorAction SilentlyContinue
if ($crashes) {
$summary = $crashes | Group-Object { ($_.Message -split "`n")[0] } |
Sort-Object Count -Descending |
Select-Object Count, Name
$summary | Format-Table -AutoSize | Out-String |
Set-Content -Path "C:\Reports\crash-report-$(Get-Date -Format 'yyyy-MM-dd').txt"
}
Explanation: -FilterHashtable with StartTime/EndTime scopes the query to exactly yesterday, and grouping by the first line of the message rolls up repeat crashes from the same faulting application into a single count instead of a wall of duplicate rows.
Tips & Tricks
Find Which Event IDs Are Most Common First
Before writing a targeted filter, this quickly shows you what's actually flooding a log — useful for figuring out which Event IDs are worth alerting on versus which are just noise.-FilterHashtable Level Numbers Aren't What You'd Guess
Level values: 1=Critical, 2=Error, 3=Warning, 4=Information, 5=Verbose. There's no Level 0 in practice for most providers. Double-check this mapping — mixing up Warning (3) and Error (2) in an alerting script is an easy mistake.Related Topics
- Services Management - Event ID 7034/7036/7031 track service state changes
- Process Management - Application crashes show up as both a process exit and an event log entry
- Logging - Building your own application logs alongside the system event log