Starting with Windows Vista and Windows Server 2008, Microsoft redesigned the Event Viewer to use a structured XML-based event log system. This means you can write XPath queries to precisely filter events, which is far more powerful than the basic filtering in the GUI. This guide covers XPath query syntax for Event Viewer, common query patterns, custom views, and how to use the same queries with command-line tools and PowerShell.
Understanding the Event XML Structure
Every event in the Windows Event Log is stored as XML. Understanding this structure is the key to writing effective XPath queries. Here is a typical event:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{...}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2024-06-15T14:30:00.000000000Z" />
<EventRecordID>123456</EventRecordID>
<Channel>Security</Channel>
<Computer>DC01.corp.example.com</Computer>
<Security UserID="S-1-5-18" />
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-5-18</Data>
<Data Name="SubjectUserName">DC01$</Data>
<Data Name="TargetUserName">john.doe</Data>
<Data Name="LogonType">10</Data>
<Data Name="IpAddress">192.168.1.100</Data>
</EventData>
</Event>
The XPath query targets elements within this XML structure.
Entering XPath Queries in Event Viewer
Method 1: Filter Current Log
- Open Event Viewer (
eventvwr.msc) - Select a log (e.g., Security)
- In the Actions pane, click Filter Current Log…
- Click the XML tab
- Check Edit query manually
- Enter your XPath query inside the
<Select>element:
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[(EventID=4624)]]</Select>
</Query>
</QueryList>
Method 2: Create a Custom View
Custom views are saved filters that persist across sessions:
- In Event Viewer, click Create Custom View in the Actions pane
- On the XML tab, check Edit query manually
- Enter your query
- Give the view a name and save it
Custom views appear under Custom Views in the left pane and run the query each time you select them.
Common XPath Queries
Filter by Event ID
*[System[(EventID=4624)]]
Multiple Event IDs:
*[System[(EventID=4624 or EventID=4625 or EventID=4634)]]
Range of Event IDs:
*[System[(EventID >= 4624 and EventID <= 4634)]]
Filter by Provider (Source)
*[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]]
Filter by Level (Severity)
| Level | Meaning |
|---|---|
| 1 | Critical |
| 2 | Error |
| 3 | Warning |
| 4 | Information |
| 0 | LogAlways (Audit) |
*[System[(Level=1 or Level=2)]]
This filters for Critical and Error events only.
Filter by Time
Last 24 hours (86400000 milliseconds):
*[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]
Last hour (3600000 milliseconds):
*[System[TimeCreated[timediff(@SystemTime) <= 3600000]]]
Specific date range:
*[System[TimeCreated[@SystemTime>='2024-01-01T00:00:00.000Z' and @SystemTime<='2024-01-31T23:59:59.999Z']]]
Filter by Computer Name
*[System[Computer='DC01.corp.example.com']]
Filter by User (Security UserID)
*[System[Security[@UserID='S-1-5-21-1234567890-1234567890-1234567890-1001']]]
Filter by EventData Fields
*[EventData[Data[@Name='TargetUserName']='john.doe']]
Filter logon events for a specific user:
*[System[(EventID=4624)] and EventData[Data[@Name='TargetUserName']='john.doe']]
Filter by logon type (10 = Remote Desktop):
*[System[(EventID=4624)] and EventData[Data[@Name='LogonType']='10']]
Combining Multiple Criteria
Security logon events for a user from a specific IP in the last 24 hours:
*[System[(EventID=4624) and TimeCreated[timediff(@SystemTime) <= 86400000]] and EventData[Data[@Name='TargetUserName']='john.doe' and Data[@Name='IpAddress']='192.168.1.100']]
All errors and warnings from a specific source in the last 7 days:
*[System[Provider[@Name='Microsoft-Windows-GroupPolicy'] and (Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) <= 604800000]]]
Practical Query Examples
Find Failed Logon Attempts
*[System[(EventID=4625)]]
Failed logon attempts from a specific IP:
*[System[(EventID=4625)] and EventData[Data[@Name='IpAddress']='192.168.1.50']]
Find Account Lockouts
*[System[(EventID=4740)]]
Find Remote Desktop (RDP) Sessions
Logon events via RDP (Logon Type 10):
*[System[(EventID=4624)] and EventData[Data[@Name='LogonType']='10']]
Find Service Installations
*[System[(EventID=7045)]]
Find System Startup and Shutdown
*[System[(EventID=6005 or EventID=6006 or EventID=6008 or EventID=6009)]]
Find Group Policy Processing Errors
*[System[Provider[@Name='Microsoft-Windows-GroupPolicy'] and (Level=2)]]
Using wevtutil from the Command Line
The wevtutil command lets you run XPath queries from the command line:
# Query the Security log for Event ID 4624
wevtutil qe Security /q:"*[System[(EventID=4624)]]" /c:10 /f:text
# Export matching events to a file
wevtutil qe Security /q:"*[System[(EventID=4625)]]" /f:xml > failed-logons.xml
# Count matching events
wevtutil qe Security /q:"*[System[(EventID=4624)]]" /c:999999 /f:text | find /c "Event"
Parameters:
qe— Query events/q:— The XPath query/c:— Maximum number of events to return/f:— Output format (text, xml, or RenderedXml)/rd:true— Read in reverse direction (newest first)
Query Remote Computers
wevtutil qe Security /q:"*[System[(EventID=4625)]]" /r:DC01.corp.example.com /u:CORP\admin /p:*
PowerShell Get-WinEvent
PowerShell provides the most flexible interface for event log queries.
Using -FilterXPath
# Failed logon attempts in the last 24 hours
Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4625) and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
# RDP logon events
Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624)] and EventData[Data[@Name='LogonType']='10']]"
# Limit results
Get-WinEvent -LogName Security -FilterXPath "*[System[(EventID=4624)]]" -MaxEvents 50
Using -FilterHashtable (Simpler Syntax)
For common queries, -FilterHashtable is easier to write:
# Events by ID and time
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625
StartTime = (Get-Date).AddDays(-7)
EndTime = Get-Date
}
# Multiple Event IDs
Get-WinEvent -FilterHashtable @{
LogName = 'System'
Level = 2 # Error
ID = 7034, 7031, 7023
}
# Events from a specific provider
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'MSSQLSERVER'
Level = 2
}
Formatting and Exporting Results
# Format as table
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} -MaxEvents 20 |
Select-Object TimeCreated, Id, Message |
Format-Table -AutoSize
# Export to CSV
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} |
Select-Object TimeCreated, Id,
@{N='User';E={$_.Properties[5].Value}},
@{N='Source';E={$_.Properties[19].Value}} |
Export-Csv -Path "C:\failed-logons.csv" -NoTypeInformation
# Query remote computers
Get-WinEvent -ComputerName "DC01" -FilterHashtable @{LogName='Security'; ID=4625}
Tips for Building XPath Queries
- Start with the GUI filter — Use the Filter Current Log dialog with the basic tabs first, then switch to the XML tab to see the generated query.
- Use Event Viewer’s Details tab — Click on any event and switch to the Details tab > XML View to see the exact XML structure and field names.
- Test incrementally — Build queries by adding one criterion at a time. Start with
*[System[(EventID=4624)]]and add filters step by step. - Watch for namespace issues — Event Viewer’s XPath implementation does not require namespace prefixes, even though events use the Microsoft schema namespace.
- Performance — Queries against the Security log on busy servers can be slow. Always use time filters to narrow the scope.
Summary
XPath queries in the Windows Event Viewer provide precise, powerful filtering that goes far beyond the basic GUI filter. The query syntax targets the XML structure of events, allowing you to filter by Event ID, provider, severity, time range, user, computer, and custom event data fields. Use the Event Viewer GUI for interactive analysis, wevtutil for command-line scripting, and PowerShell Get-WinEvent for automation and reporting. Start by examining an event’s XML structure, then build your query step by step.