Scope & evidence

Local Windows event logs and saved EVTX files using Windows PowerShell 5.1 or PowerShell 7 on Windows. Log permissions still apply. Named event-data filtering requires PowerShell 6 or later.

The examples are checked against Microsoft documentation. They are illustrative commands, not output from a Windows test or a performance benchmark. No production event logs were accessed for this guide.

Start with one log and a short time window

For a first pass, query the last two hours of the local System log and return no more than 100 matching events. The example captures the end time once, so the start and end describe one fixed window. It reads events; it does not clear logs, change logging or restart services.

Run this on Windows with permission to read the chosen log. PowerShell 7 on Linux or macOS cannot run Get-WinEvent. Start with the access your organisation has approved; an access-denied result is a permissions problem to resolve, not an instruction to change the log ACL.

The normal return order is newest first. Exactly 100 results means the limit may have cut off older matches. Fewer results still do not prove that collection was complete: check errors, retention and whether you selected the correct machine and channel.

$end = Get-Date
$filter = @{
    LogName   = 'System'
    StartTime = $end.AddHours(-2)
    EndTime   = $end
}
Get-WinEvent -FilterHashtable $filter -MaxEvents 100 |
    Select-Object TimeCreated, MachineName, LogName,
        ProviderName, Id, RecordId, LevelDisplayName, Message

Choose filters that answer the incident question

Use one criterion at a time until you have confirmed a known event. A provider name and an event ID together usually describe a more useful question than an ID across every provider. For a service incident, start with the service name, machine and timestamp from the original symptom.

Put LogName inside the hashtable when using FilterHashtable. Keep MaxEvents outside it as a cmdlet parameter. Use numeric values for severity: 1 is critical, 2 error and 3 warning. An array such as Level = 2,3 selects either error or warning events within the other criteria.

Only LogName and ProviderName support wildcard values among the keys shown below. Do not assume that Message is a supported full-text filter key. For a complex query, Event Viewer can generate XML for Get-WinEvent -FilterXml; keep that as a separate query method.

CriterionHashtable examplePractical check
ChannelLogName = 'System'Confirm the exact channel, not a file path
ProviderProviderName = 'Service Control Manager'Confirm the provider on a known event
Event IDId = 7036Combine with the relevant provider and channel
SeverityLevel = 2,3Errors or warnings; information events are excluded
TimeStartTime = $end.AddHours(-2)Record the end time and the time zone too
Saved logPath = 'C:\Incident\System.evtx'Read an authorised exported file

Narrow by provider and event ID

This independent example requests recent Service Control Manager events with ID 7036. It is a query example, not a promise that your system recorded that event. Adjust the ID and provider using an event you have already confirmed in Event Viewer.

Do not add a severity condition reflexively. A useful state-change event may be informational, so an errors-only filter can remove the very transition you need. Record why each criterion belongs in the query; remove the last added criterion if a previously visible known event disappears.

$end = Get-Date
Get-WinEvent -FilterHashtable @{
    LogName      = 'System'
    ProviderName = 'Service Control Manager'
    Id           = 7036
    StartTime    = $end.AddHours(-2)
    EndTime      = $end
} -MaxEvents 100 |
    Select-Object TimeCreated, ProviderName, Id, RecordId, Message

Search message text after narrowing the query

For a phrase in the rendered Message property, first restrict the channel and time range, then use Where-Object on that smaller result. The example searches for the illustrative word timeout, case-insensitively. Substitute a phrase from the actual incident.

There is deliberately no MaxEvents in this example: a cap before Where-Object would search only that capped subset. Keep the time window short and split a large investigation into reviewed intervals. This is an inspection query, not a guarantee of bounded memory or a measured speed improvement.

Rendered messages can vary with language and installed provider resources. A missing phrase is weaker evidence than a matching structured field. Where an event exposes a named data field, PowerShell 6 and later can filter it by its exact case-sensitive field name. Inspect the event XML first; do not copy an arbitrary field name into a Windows PowerShell 5.1 query.

$end = Get-Date
Get-WinEvent -FilterHashtable @{
    LogName   = 'System'
    StartTime = $end.AddMinutes(-30)
    EndTime   = $end
} | Where-Object { $_.Message -like '*timeout*' } |
    Select-Object TimeCreated, ProviderName, Id, RecordId, Message

Keep no matches separate from a failed query

Get-WinEvent can report an error when nothing matches. Do not suppress every error and then declare the system healthy. Record whether the query completed without matches, lacked access, selected a missing log or failed for another reason.

If automating this procedure, use ErrorAction Stop where you need terminating-error handling and inspect the error in catch. A catch block that converts every failure into an empty array loses the distinction between absence of evidence and unavailable evidence. Validate the no-match case on your supported Windows and PowerShell versions before scheduling it.

A useful recovery order is: confirm the computer and channel; inspect a recent known event; check the incident time and time zone; then add provider, ID and severity. If the interval is no longer retained, seek an authorised archive or central collector. Re-running a narrower query cannot recover overwritten records.

ObservationNext checkConclusion to avoid
No matching eventsTime zone, known event, filters and retentionThe incident did not happen
Access deniedApproved execution identity and log permissionsThe log is empty
Exactly the maximum countNarrow the interval or review an uncapped queryThis is the complete period
Message unavailableProvider resources and structured event dataThe event contains no useful evidence

Export a review copy without discarding the original

Keep the queried records as objects until export. Select a stable field set and use Export-Csv without an intervening Format-Table. The following example creates a small review CSV from an existing, authorised System.evtx export. Prepare the destination folder first and choose a new filename; NoClobber prevents overwriting an existing report.

The 200-event limit makes this a sample. CSV contains the selected fields, not the complete EVTX structure. Keep the original EVTX under the incident access and retention policy. Microsoft documents separate wevtutil export-log and archive-log operations when you need an event-log export or a self-contained archive; clearing a log is a different operation and is unnecessary here.

Messages may contain account names, paths or customer information. Review before sharing. If opening a CSV in a spreadsheet, import untrusted text as text so message content is not interpreted as a formula. Do not attach raw logs to a public support thread.

Get-WinEvent -FilterHashtable @{
    Path = 'C:\Incident\System.evtx'
    Level = 2,3
} -MaxEvents 200 |
    Select-Object TimeCreated, MachineName, LogName,
        ProviderName, Id, RecordId, LevelDisplayName, Message |
    Export-Csv -LiteralPath 'C:\Incident\event-review.csv' `
        -NoTypeInformation -Encoding UTF8 -NoClobber

Close the investigation with a reproducible record

Suppose a fictional service interruption starts at 09:10 and recovers at 09:16. Review a surrounding interval, such as 09:00 to 09:30 in the recorded incident time zone, rather than searching only the minute of recovery. Correlate service events with the application log and the user-facing symptom. A nearby event is a lead; timing alone does not prove causation.

In another hypothetical review, a capped query returns 100 of 140 matching records. That is about 71.4% of the matching records, but the administrator cannot infer the total of 140 from the capped result alone. Establish it independently with a complete, successful query or an appropriate retained evidence set. Never use the capped count as the incident frequency.

Use the editable worksheet below to keep the machine, channel, criteria, shell version, time zone, result cap, errors and evidence paths together. End with the next decision and its owner. A colleague should be able to understand what you searched and what remains unknown without rerunning commands on production.

References

Next useful steps

Read our editorial and corrections policy.