wevtutil qe to Query Events

(This does exist in Windows 7, and newer versions of Microsoft Windows. (It might not have existed in Windows XP? For more details about other ways to get logs, see Windows Event Logs: section about viewing the logs.))

The qe can be used to query events.

Here is an actual example showing quite a few options. (You do NOT need all of these options! Many are optional.)

wevtutil qe System /q:" ( Event/System/Provider/@Name='EventLog' or Event/System/Provider/@Name='Microsoft-Windows-EventLog' ) and ( Event/System/Level=0 or Event/System/Level=4 ) and ( Event/System/EventID=6005 or Event/System/EventID=6013 ) and ( Event/System/TimeCreated[timediff(@SystemTime) <= 86400000 ] ) and Event/System/TimeCreated/@SystemTime >= '2016-12-31T23:59:59' and Event/System/TimeCreated/@SystemTime <= '9999-12-31T23:59:59' and Event/EventData/Data='480 Pacific Standard Time' " /f:RenderedXML /rd:true /c:1 /r:localhost

Some quick notes:

When using the overly-verbose /f:RenderedXML, if an object is found then you can see the XML tags. An approximate example may help show how the output corresponds to the text used in the query.

<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System>
<Provider Name='EventLog'/><EventID Qualifiers='32768'>6013</EventID>
<Level>4</Level><Task>0</Task><Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime='YYYY-MM-DDTHH:mm:ss.mmmnnn###'/>
<EventRecordID>2866</EventRecordID><Channel>System</Channel>
<Computer>localhost</Computer><Security/></System>
<EventData><Data></Data><Data></Data><Data></Data><Data></Data>
<Data>2233447</Data><Data>60<Data><Data>480 Pacific Standard Time</Data>
<Binary>########################################################################
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
################################################################################
########################</Binary>
</EventData>
<RenderingInfo Culture='en-US'>
<Message>The system uptime is ####### seconds.</Message>
<Level>Information</Level><Task></Task></Opcode></Opcode><Channel></Channel>
<Provider></Provider><Keywords></Keyword>Classic</Keyword></Keywords>
</RenderingInfo>
</Event>

John Howard's “Getting event log contents by email on an event log trigger” on TechNet indicates that “an answer” (and not necessarily “the” best/only answer) for “the easiest way to get the last instance of” a specific event is to use a command line like the one he provided, which roughly looks something like this:

wevtutil qe logName "/q:*[System[(EventID=#####)]]" /f:text /rd:true /c:1 /r:sysName

e.g.:

wevtutil qe System "/q:*[System[(EventID=20274)]]" /f:text /rd:true /c:1 /r:localhost

Note that in the above example, the second word “System” is NOT the name of the log. It is literal text.

The word following the qe parameter helps the program choose what available logged data to use. (In the above example, the first word “System” specifies what logged data to use.) The built-in help calls this parameter the “PATH” (completely unrelated to the PATH environment variable). This parameter specifies the name of a log, unless the /lf parameter changes the way that the log data gets specified.)

A couple of ways to get a feel for the structure of the referencable objects/names by seeing some of the XML output shown later in this documentation, or by getting some successful results and rendering the output using /f:RenderedXML.

The square brackets help notate levels in a heirarchy. A forward slash can also be used effectively to do the same thing. So, this may be a shorter way to run the above:

wevtutil qe System "/q:*[System/EventID=20274]" /f:text /rd:true /c:1 /r:localhost

Online help for the command is available:

wevtutil qe /?
An example

Here is another example, at least partially inspired by “Admin On the Run” blog: “wevtutil, my new favorite toy”:

Note that this should be done from a UAC-elevated command prompt:

wevtutil qe System /q:"*[System[Provider[@Name='eventlog' or @Name='Microsoft-Windows-Eventlog'] and (Level=1 or Level=2 or Level=3 or Level=4 or Level=5 or Level=0) and (EventID=6005 or EventID=6006 or EventID=6008 or EventID=6013) and TimeCreated[timediff(@SystemTime) <= 86400000]]]" /c:5 /f:text /rd:True /r:localhost

That can certainly be customized. Before discussing a method of creating a string from scratch, let's look at the pieces of the prior example:

wevtutil
Executable name
qe
qe is short for query-events
System

The word right after the “qe” is the log file.

(Perhaps this is the “channel”, using terminology from MSDN: Event Selection. When dealing with a typical *.evtx log files, the “channel” of information is the log, and the file contains just one log file, so there's no substantial difference. Essentially, examples and experience have indicated that what gets specified here is the name of the log and/or the log file.)

(Note, the word “System” may appear more than once, and for different reasons. If the word “System” appears right after the “qe” command code, then that word is specifying that the “system” log be used. The word “System” can (also) appear in another location of the command line, and have an entirely different meaning when it does.)

Note: A way you can see the location of the logs is to open up EventVwr.msc, then use the “context-sensitive menu”/“context menu”/“shortcut menu”/“alternate menu”/“secondary menu”/“right-click menu” of the log, and choose Properties. e.g., in Windows 10, classic logs may point to a %SystemRoot%\System32\Winevt\Logs\*.evtx file. (This GUI option may even show a reference to that environment variable name, by default.)

/q:

This mandatory part of the command begins to specify the query.

Using the Event Log Viewer's “Filter Current Log” screen (in Windows Vista and newer) is an easy way to determine some text that can be useful for a query. After using the GUI to specify what is desired, the XML path's “Select” tag will show some text.

The syntax is rather close to XPath. (MSDN: Event Selection notes, “Windows Event Log does not implement the full functionality of XPath 1.0. It only implements the features of XPath 1.0 which are useful in the eventing and logging scenarios. The primary restriction is that only XML elements that represent events can be selected by an event selector. An XPath query that does not select an event is illegal. Because all event elements are named Event, all valid selector paths start with * or Event.” The page goes on to provide a bit more information.) Since XPath is mostly supported, using something like the word AND can work. (Further details can be seen from this W3C page: XML Path Language, a.k.a. “XPath”.) Specifically, and is one of the operators mentioned by Windows Dev Center: Consuming Events: XPath 1.0 limitations.

The examples on this page (or, probably most of them, anyway) tend to use lowercase or, as well as lowercase and. Although uppercase is what was documented by Windows Dev Center: Consuming Events: XPath 1.0 limitations, in at least one version, wevtutil was not recognizing the uppercase words (and so it rejected the queries due to an invalid syntax). Lowercase also works, and therefore is likely what many people will use when typing manually (especially for single-time use, rather than when creating re-usable code).

Name
Looking at the “Source” of the event
Level=
Choose the Windows “Event Level” (which is effectively how to specify which Windows “Event Type” to use).

MSDN page indicates a possibly shorter query: "*[System/Level=1]"

(If you're wondering what level is used by a specific event, and have managed to isolate that event using other methods, you can leave off the /f:text, so then the level number will show in the output. Or, you could just decide to not make the Level be part of the filter.)

EventID
Event ID. May be useful when using online resources for Windows event logs.
TimeCreated[timediff(@SystemTime) <= 86400000]

This syntax causes the “timediff(” function to compare the event's SystemTime variable (which is part of a containing object named TimeCreated, which is also part of the event). Since the “timediff(” parameter did not receive an optional second parameter, the specified time will be compared to the current system time. 86400000 is the number of milliseconds in a day. For your convenience, here is a handy list of some amounts of milliseconds:

  • 3600000 is the number of milliseconds in an hour.
  • 86400000 is the number of milliseconds in a day.
  • 604800000 is the number of milliseconds in a week.
  • 1209600000 is twice that.
]]
Corresponds to the two left square brackets from “[System[”.
/c:5
Maximum count: only this number of events will be shown
/f:text

Set the output format to be text. Another possibility is “/f:XML” which “wevtutil qe -?” identifies as the default, and as the option which is faster than “/f:text” or “/f:RenderedXML”. Using “/f:RenderedXML” is like “/f:XML” but adds an opening XML tag called “<RenderingInfo>”, some more content, and a matching closing “</RenderingInfo>” tag. That additional content contains information about what some of the fields will look like (rendered in the language of the operating system), including the quite useful “Description” field typically shown by Event Viewer.

wevtutil qe -?” shows us that “/f:” is short for “/format:”. (Full fuller name may be used instead, if desired.)

/rd:True

wevtutil qe -?” shows us that “/rd:” is the short version for “/reversedirection”. (Full fuller name may be used instead, if desired.)

Reverse Direction, so things are in reverse-chronological order (showing newest events first). (Perhaps the order is only typical, assuming that the log is sorted by time.) This is an optional parameter, so if this doesn't get specified, then the newest events (typically?) come last.

/r:localhost

This specifies a “remote system” named localhost. Actually, the example shown is rather useless to actually type/use, but this example is shown anyway so a person can easily see what to customize if connectivity to a remote system is actually desired. If the computer to be worked on is actually localhost, that's technically not even truely a “remote” system, and the whole optional “/r:systemName” portion can be left off entirely.

Another example: Parsing Security Log

Note that this should be done from a UAC-elevated command prompt:

wevtutil qe Security /q:"*[System[(EventID=4624 or EventID=4634 or EventID=4672 or EventID=672) and TimeCreated[timediff(@SystemTime) <= 1209600000] and (Level=0)]] and *[EventData/Data[@Name='LogonType']='2' or EventData/Data[@Name='LogonType']='7'] and *[EventData/Data[@Name='TargetUserName']='accountName']" /f:text /rd:true /c:10 /r:localhost | find /i "Date: "

In the above example, the username probably needs to be customized.

At present, the above is meant to show a command using correct syntax. Some of the options, like Level and Event IDs, might not match too well. The intent is simply to show correct form, allowing a user to customize anything that is wanted. The best approach for unnecessary details may be to leave them off.

qe
A shortcut for query-events
Security
The name of the log file. See: %SystemRoot%\System32\Winevt\Logs\*.evtx
(EventID=4624 or EventID=4634 or EventID=4672 or EventID=672)

SANS PDF page 20 and SANS PDF page 21 show that the Event IDs used will depend on what operating system is being used. For instance:

  • a successful logon may use Event ID 528 in Windows 2000, Windows XP, and Windows 2003,
  • or may use Event ID 540 in Windows 2000, Windows XP, and Windows 2003,
  • while either of those types of events may use Event ID 4624 in Windows 7 and newer (at least up through 2012).

Doing some research, some researching with Google revealed that:

TimeCreated[timediff(@SystemTime) <= 1209600000]
Number of milliseconds in 2 weeks. (1,209,600,000 milliseconds = 1,209,600 seconds, divided by 60 = 20,160 minutes, divided by 60 = 336 hours, divided by 24 = 14 days, divided by 7 = 2 weeks.)
(Level=0)

This restricts the output to log entries with Level 0, which would indicate an informational event.

*[EventData/Data[@Name='LogonType']='2'

Specifies interactive logons. Logon types are mentioned by:

/r:localhost

This optional part uses the technologies that permit remote access to WMI data. A different computer name can be specified.

| find /i "Date:"
Shows the date-stamp (which includes the date, and time) of the events.
http://serverfault.com/questions/571732/filtering-security-logs-by-user-and-logon-type

One way to easily get the part between the quotation marks is to use eventvwr.msc and select “Filter Current Log...”, choose some options, and view the XML tab.

Karl's 24 Jul 2012 8:37 PM comment (to John Howard's “Getting event log contents by email on an event log trigger” on TechNet) discusses getting the last three events. Mike's 16 Apr 2013 4:48 PM comment shows some similarities to the query (on the command line) and information obtainable from the XML version of the event data.

Some online documentation for the program is available: WindowsSecurity.com: Using WEVTUTIL to Manage Event Logs (article by Derek Melber).

Another example: Checking if a specific service has changed status

Some of this example might make a bit more sense with some more details about the context. This example was created when investigating a situation described by Windows Devices: Hard drives and partitions: Identifying a (named, data storage) “\Device\.

In this example, an automated process realized that an event happened at a specific time, such as 3:26 PM PDT (Pacific Daylight Time). (Pacific Standard Time (“PST”) is -0800, but PDT is only -0700.) The goal was to find out whether a service containing the name “Enumerator” was started or stopped within a short time (say, 15 minutes) of this other event.

First, some of the commands that were used are shown. Later, there's some more details about how the 'param1' value was chosen.

Note that this should be done from a UAC-elevated command prompt:

wevtutil qe System /q:"*[System[Provider[@Name='Service Control Manager' and @EventSourceName='Service Control Manager'] and (EventID=7036) and (Level=4 or Level=0) and TimeCreated[@SystemTime>='2016-01-25T13:20:00' and @SystemTime<='2016-01-25T17:50:00']]]" /f:text /rd:true /c:10 /r:localhost | find /i "Enumerator:"

Most of the above example shows details similar to other examples, so they aren't all being documented here.

  • One item of note is that the two times need to be customized.
    • Note: When wevtutil outputs the logs, the output may show: “Date: ” followed by a time in the system's local time zone. However, that is not the format that wevtutil expects as input. So, manual conversion may be needed.

The results of this command don't show all of the details related to the event. That is because of some of the filtering of the find command. However, the output does show a couple of details:

  • You can easily see how many events fit within the time period. If the answer is zero, then there is no need to try to get further details about individual events that didn't occur.
  • You can see the precise name of the service. In this case, there are multiple services that we are actually potentially interested in. Names may include at least “Portable Device Enumerator Service” or “PnP-X IP Bus Enumerator”. Different computers have been known to use different names, and in this example, we are actually interested in either one of these services.
  • If retrieving logs is very slow, it may be worthwhile to not filter this through the FIND command. Instead, the technique of redirecting the output to a text file could be used. That way, the results can be re-used a bit without needing to repeat the slow search. The text file could then be searched, separately, to see how many times the word Enumerator showed up. Then, some of the later instructions might also be slower than just manually reviewing the text file. (So, some of the later instructions here may only be ideal to use on computers that can produce the search results quickly.)

So, now that we know the name of the Enumerator service we are looking for, more details about each of those events can be seen by running something like this:

wevtutil qe System /q:"*[System[Provider[@Name='Service Control Manager' and @EventSourceName='Service Control Manager'] and (EventID=7036) and (Level=4 or Level=0) and TimeCreated[@SystemTime>='2016-01-25T13:20:00' and @SystemTime<='2016-01-25T17:50:00']]] and *[EventData/Data[@Name='param1']='Portable Device Enumerator Service']" /f:text /rd:true /c:10 /r:localhost | more
  • The times should be customized. (They can be, and probably ought to be, the same as the previous command.)
  • Depending on the computer being used, the exact name of the service may vary. So the 'Portable Device Enumerator Service' might be something that needs to be changed. Or, that might be exactly right.

One way to easily get much of the syntax between the quotation marks is to use eventvwr.msc and select “Filter Current Log...”, choose some options, and view the XML tab. That is, for example, how the Level=4 or Level=0 was used to restrict results to Informational events.

Now, as promised, some details about how the “*[EventData/Data[@Name='param1']='ServiceName']” was figured out:

First, some events were found, showing some services that started. This search didn't have the results filtered for a specific service, but did check for any services:

wevtutil qe System /q:"*[System[Provider[@Name='Service Control Manager' and @EventSourceName='Service Control Manager'] and (EventID=7036) and (Level=4 or Level=0) and TimeCreated[timediff(@SystemTime) <= 86400000]]]" /f:text /rd:true /c:10 /r:localhost | more

This showed some events. Results looked something like:

Event[0]:
  Log Name: System
  Source: Service Control Manager
  Date: YYYY-MM-DDThh:mm:ss.mmm
  Event ID: 703#
  ...
  Description:
The ServiceName service...

Event[1]:
  Log Name: System
  Source: Service Control Manager

Then, this was rendered with XML instead. Note the change to the /f: parameter.

wevtutil qe System /q:"*[System[Provider[@Name='Service Control Manager' and @EventSourceName='Service Control Manager'] and (EventID=7036) and (Level=4 or Level=0) and TimeCreated[timediff(@SystemTime) <= 86400000]]]" /f:RenderedXML /rd:true /c:10 /r:localhost | more

The results were a bit more time-consuming to read, but did provide some more useful details. The results looked somewhat similar to the following:

<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Service Control Manager' Guid='{555908d1-a6d7-4695-8e1e-26931d2012f4}' EventSourceName='Service Control Manager'/><EventID Qualifiers='#'>703#</EventID>...<Level>2</Level>...<TimeCreated SystemTime='2017-02-15T23:38:08.251481600Z'/>...<Execution ProcessID='#' .../><Channel>System</Channel><Computer>systemHostName</Computer><Security/></System><EventData><Data Name='param1'>serviceName</Data><Data Name='param2'>...</EventData><RenderingInfo ...><Message>The serviceName service ...</Message><Level>Error</Level>...<Provider>Microsoft-Windows-Service Control Manager</Provider><Keywords><Keyword>Classic</Keyword></Keywords></RenderingInfo></Event>
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name=...

We can see from output we can see there is an “opening” XML tag called “<EventData>”. Then, before the matching (“</EventData>”) “closing” tag, there are multiple “<Data” tags. Each of them has an XML attribute called Name. One of those “<Data” tags had a Name attribute which had a corresponding value of “'param1'”. Inside that “<Data” tag, there was the desired information (which, for this example, was the name of the service).

Looking over that information, some sample syntax was played with until useful results were obtained by using this in the query: “*[EventData/Data[@Name='param1']='ServiceName']

So, the author of this text interprets that command roughly as follows: for any EventData's sub-object named Data which has an XML attribute called Name and the corresponding value of “'param1'”, compare the content of that tag and see if that content equals the customized 'ServiceName' specified on the command line.

Misc/related notes

Social page refers to schema.

http://stackoverflow.com/a/15943185 (Date)

The EventSource name is limited to 21 characters. I discovered it via trial and error. If you specify a longer name nobody complains not when you create the event source and not when you write an entry. However, the entry is simply not recorded. I checked the interwebs and saw no mention of it. Either everybody is using short source names or something else is going on.