Windows event log querying from the command line: wevtutil (with XPath query parameters and XML output)
Posted by jpluimers on 2025/04/23
A while ago, I needed to investigate reboot events on some Windows 10 systems. I wanted to use the console instead of the eventvwr GUI Event Viewer.
There is a tool for that called wevtutil which – like eventvwr – uses XPath query parameters and produces XML output.
Postprocessing XML can be a thing, but since .NET has great XML support, you can use PowerShell for that (which for me often is way easier than going the XSLT route, for instance because Windows lacks built-in console XSLT tooling).
Based on the help and the below links, my query command then on these machines turned out to be this:
wevtutil query-events System /reversedirection:true "/query:*[System[EventID=6005 or EventID=6006]]" > reboot-events.xml
I expanded all options to their full form except reverseddirection, as despite the built-in help – see [Wayback/Archive] wevtuti built-in help: “wevtutil /?” and “wevtutil query-events /?” – it is not supported (bug alert!):
Invalid option reverseddirection. Option is not supported. The parameter is incorrect.
Some links for both my link archive and if you are interested to play around with this:
- [Wayback/Archive] How to find out the last time Windows rebooted and started up
- Event ID 6006: “The event log service was stopped.” This is synonymous to system shutdown.
- Event ID 6005: “The event log service was started.” This is synonymous to system startup.
- [Wayback/Archive] How to query logs in Event Viewer using the command line (which explains about
wevtutilwhich is available as of Windows Vista) - [Wayback/Archive] wevtutil | Microsoft Learn
Enables you to retrieve information about event logs and publishers. You can also use this command to install and uninstall event manifests, to run queries, and to export, archive, and clear logs.
- [Wayback/Archive] windows – Wevtutil\Event Viewer: Getting list of events with different event ids using XPath Filter – Stack Overflow (thanks [Wayback/Archive] Anthony J. and [Wayback/Archive] Eryk Sun):
Q
I need to get a list of events that have id of 6005 or 6006 using “wevtutil” tool. This command works fine:wevtutil qe system /rd:true /q:*[System[EventID=6005]]But I need to get both events with ID 6005 and 6006. I triedwevtutil qe system /rd:true /q:*[System[EventID=6005 or EventID=6006]]But it returnsToo many arguments are specified. The parameter is incorrect.How should I fix it?C
wevtutil.exeuses the C runtime’swmainentry point, which tokenizes the command line according to the rules documented in [Wayback/Archive] Parsing C++ Command-Line Arguments. So you need double quotes to prevent the query from getting split as separate arguments, e.g."/q:*[System[EventID=6005 or EventID=6006]]"or even odd-looking/q:*[System[EventID=6005" or "EventID=6006]]. - [Wayback/Archive] `main` function and command-line arguments (C++) | Microsoft Learn
- [Wayback/Archive] windows server 2008 – Parse wevtutil XML into a database? – Server Fault (thanks [Wayback/Archive] Skyhawk and [Wayback/Archive] sysadmin1138):
Q
I’m by no means an XML expert. Ergo, I’m having trouble importing Windows event XML from wevtutil into an SQL database.
…
(note: this would be a recurring process, so it can’t require GUI-only tools.)
A
I’m doing exactly this in a script by way of PowerShell.…
The command to get the event data is what you already know.wevtutil qe Security /r:$DC /q:"*[System[((EventID=$LogonID or EventID=$FLogonID or EventID=$LogoffID or EventID=$LockoutID) and TimeCreated[@SystemTime > '$LUFilterString'] and TimeCreated[@SystemTime < '$NowFilterString'] )]] " > $DC-events.xmlThe variables in that should be clear. I’m tracking login, logout, and lockout events. Generating the “NowFilterString” in the funny format wevtutil requires:$Now=get-date $Msec=$now.Millisecond $NowFilterString=$Now.AddSeconds(-1).AddMilliseconds(-$Msec).ToUniversalTime().ToString("O")I’m truncating the milliseconds down to zero to better handle edge cases.So now you have an XML file. Now what? To parse that XML file:get-content ".\$DC-events.xml" | foreach { $Event=[xml]$_ $DateTime=[datetime]$Event.event.System.TimeCreated.GetAttribute("SystemTime") codecodecodecode }Accessing individual elements is done by:foreach ($Data in $Event.event.EventData.get_childNodes()) { if ($Data.Name -eq "TargetUserName") { $User=$Data."#text"} elseif ($Data.Name -eq "IpAddress") {$IP=$Data."#text"} }Or another exampleforeach ($Data in $Event.event.EventData.get_childNodes()) { if ($Data.Name -eq "TargetUserName") {$User=$Data."#text"} elseif ($Data.Name -eq "WorkstationName") {$MachineName=$Data."#text"} elseif ($Data.Name -eq "IpAddress") {$IP=$Data."#text"} # Ensure only failed logins to the right domain are processed: elseif ($Data.Name -eq "TargetDomainName") {$Domain=$Data."#text"} }I hope this helps you figure out XML parsing. Since this is PowerShell, most of these are readily convertible to standard .NET calls.
In the search queries used, you can see that a some moments I was not exactly sure what to search for, but Google luckily gave relevant results nonetheless:
- [Wayback/Archive] eventvwr last reboots – Google Search
- [Wayback/Archive] query eventvwr from console – Google Search
- [Wayback/Archive] wevtutil “reboot” query – Google Search
- [Wayback/Archive] wevtutil 6005 – Recherche Google
- [Wayback/Archive] wevtutil parse – Google Search
--jeroen
https://gist.github.com/jpluimers/3a198160e4aa0ab3596ccf3ec9dcc03a






Leave a Comment