Querying Windows Event Logs with PowerShell | Windows OS Hub (2024)

The Windows Event Log is an important tool for administrators to track errors, warnings, and other information reports that are logged by the operating system, its components, or programs. You can use the Event Viewer graphical MMC snap-in (eventvwr.msc) to view the Windows event log. In some cases, it is much more convenient to use PowerShell to parse and analyze information from the Event Logs. In this article, you’ll learn how to use the Get-WinEvent cmdlet to get information from the Windows event logs.

Contents:

  • Get-WinEvent: Search the Event Logs Using PowerShell
  • Fast Event Search with the FilterHashtable Option
  • Advanced Get-WinEvent Filtering with FilterXml
  • Get Event Logs from Remote Computers

Two cmdlets for accessing event log entries are currently available in Windows: Get-EventLog and Get-WinEvent. We recommend that you use Get-WinEvent in most cases, as it is more productive, especially in scenarios where you need to process a large number of events from remote computers. The Get-EventLog cmdlet is deprecated and was used to get logs in earlier versions of Windows. Also, Get-EventLog is not supported in the latest versions of PowerShell Core 7.x.

Get-WinEvent: Search the Event Logs Using PowerShell

To use the Get-WinEvent command, you must run PowerShell as an administrator. If you try to run Get-WinEvent as a non-admin user, you will not be able to access certain logs, including the Security logs.

To get a list of events from a specific log, you must specify its name. For example, the following command lists the last 20 events from the System log:

Get-WinEvent -LogName Application -MaxEvents 20

System, Application, Security, or Setup logs are the most common logs to query. You can also specify other log names. You can get a full list of event logs in Windows with the command:

Get-WinEvent -ListLog *

Querying Windows Event Logs with PowerShell | Windows OS Hub (1)

For example, to view the RDP connection history on a computer, you must specify the Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational log:

Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational

Or you can get the SSH connection logs in Windows from the OpenSSH/Operational log:

Get-WinEvent -LogName OpenSSH/Operational

You can also select events from multiple logs at once. For example, if you want to get information about errors and warnings from System and Application logs for the last 24 hours, use the following code:

$StartDate = (Get-Date) - (New-TimeSpan -Day 1)
Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}

Querying Windows Event Logs with PowerShell | Windows OS Hub (2)

You can use the Select-Object or Format-Table cmdlets to display only specific event fields:

Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID
Querying Windows Event Logs with PowerShell | Windows OS Hub (3)

You can further process data obtained from the event log. In this example, we will immediately convert the username to SID:

Get-WinEvent -filterhash @{Logname = 'system'} |
Select-Object @{Name="Computername";Expression = {$_.machinename}},@{Name="UserName";Expression = {$_.UserId.translate([System.Security.Principal.NTAccount]).value}}, TimeCreated

Fast Event Search with the FilterHashtable Option

The above method of filtering specific events from the Event Viewer logs with Where-Object may be easy to understand, but it is extremely slow, especially if you want to search through a large number of events. In most cases, it’s better to use Event Viewer server-side filtering using the FilterHashtable option.

Now, let’s try to generate a list of errors and warnings over a 30-day period using Where-Object and FilterHashtable. We will then use Measure-Command to compare the execution time of these two PowerShell commands:

$StartDate = (Get-Date).AddDays(-30)

First, we check the execution time of the command with the Where-Object filter:

(Measure-Command {Get-WinEvent Application,System | Where-Object {($_.LevelDisplayName -eq "Error" -or $_.LevelDisplayName -eq "Warning") -and ($_.TimeCreated -ge $StartDate )}}).TotalMilliseconds

The same command with FilterHashtable:

(Measure-Command {Get-WinEvent -FilterHashtable @{LogName = 'System','Application'; Level =2,3; StartTime=$StartDate }}).TotalMilliseconds

This example shows that the FilterHashtable event filtering command is 30 times faster than the usual Where-Object filter ( 2.5 secs vs 76 secs).

Querying Windows Event Logs with PowerShell | Windows OS Hub (4)

If you need to find events by EventID, use the following command with the FilterHashtable parameter:

Get-WinEvent -FilterHashtable @{logname='System';id=1074}|ft TimeCreated,Id,Message

In this example, we have received the latest Windows reboot and shutdown events, allowing us to determine who rebooted or shut down the Windows machine.

The FilterHashtable argument allows you to filter by the following event attributes:

  • LogName
  • ProviderName
  • Path
  • Keywords (use 9007199254740992 to search for successful events and 4503599627370496 for failed ones)
  • ID
  • Level (1=FATAL, 2=ERROR, 3=Warning, 4=Information, 5=DEBUG, 6=TRACE, 0=Info)
  • StartTime
  • EndTime
  • UserID (user’s SID)
  • Data

Here’s an example of searching for an event over a certain period of time:

Get-WinEvent -FilterHashTable @{LogName='System'; StartTime=(get-date).AddDays(-7); EndTime=(get-date).AddHours(-1); ID=1234}

The command below can be used if you want to find specific text in the event description:

Get-WinEvent -FilterHashtable @{logname='System'}|Where {$_.Message -like "*USB*"}

Querying Windows Event Logs with PowerShell | Windows OS Hub (5)

Advanced Get-WinEvent Filtering with FilterXml

The Get-WinEvent filters with the FilterHashtable option have some limitations. If you need to use complex queries with many criteria to select events by, you need to use the FilterXml flag, which allows you to make the selection using an XML query. Similar to FilterHashtable, FilterXml filters are server-side. This means you get the result pretty quickly.

For example, here’s another way to get the most recent errors from the System log for the last 30 days:

$xmlQuery = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery

Querying Windows Event Logs with PowerShell | Windows OS Hub (6)

To generate a complex XML query code, you can use the Event Viewer graphical console:

  1. Run the command eventvwr.msc ;
  2. Find the log you want to create a query for and click Filter Current Log; Querying Windows Event Logs with PowerShell | Windows OS Hub (7)
  3. Select the required query parameters in the filter form. In this example, I want to find events with specific EventIDs for the last 7 days for a specific user; Querying Windows Event Logs with PowerShell | Windows OS Hub (8)
  4. To get the XML query code, go to the XML tab, and copy the XPath code (CTRL+A, CTRL+C);Querying Windows Event Logs with PowerShell | Windows OS Hub (9)
  5. You can edit this query manually if necessary.

To export the list of events to a CSV file, use the Export-CSV cmdlet:

$Events= Get-WinEvent -FilterXML $xmlQuery
$events| Export-CSV "C:\ps\FilterSYSEvents.csv" -NoTypeInformation -Encoding UTF8

Get Event Logs from Remote Computers

To get events from a remote computer, simply specify its name in the -ComputerName parameter:

$computer='mun-dc01'
Get-WinEvent -ComputerName $computer -FilterHashtable @{LogName="System"; StartTime=(get-date).AddHours(-24)} | select Message,Id,TimeCreated

You can query multiple remote hosts at once to search for specific events. You can get the list of remote computers from a text file:

$servers = Get-Content -Path C:\ps\servers.txt

Or from Active Directory:

$servers = (Get-ADComputer -Filter 'operatingsystem -like "*Windows Server*" -and enabled -eq "true"').Name
foreach ($server in $servers) {
Get-WinEvent -ComputerName $server -MaxEvents 5 -FilterHashtable @{
LogName = 'System'; ID= 1234
} | Select-Object -Property ID, MachineName
}

Here is another example of searching for user account lockout events on all domain controllers:

$Username = 'a.muller'
Get-ADDomainController -fi * | select -exp hostname | % {
$GweParams = @{
'Computername' = $_
'LogName' = 'Security'
'FilterXPath' = "*[System[EventID=4740] and EventData[Data[@Name='TargetUserName']='$Username']]"
}
$Events = Get-WinEvent @GweParams
$Events | foreach {$_.Computer + " " +$_.Properties[1].value + ' ' + $_.TimeCreated}
}

Querying Windows Event Logs with PowerShell | Windows OS Hub (2024)

References

Top Articles
Latest Posts
Article information

Author: Fredrick Kertzmann

Last Updated:

Views: 5655

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Fredrick Kertzmann

Birthday: 2000-04-29

Address: Apt. 203 613 Huels Gateway, Ralphtown, LA 40204

Phone: +2135150832870

Job: Regional Design Producer

Hobby: Nordic skating, Lacemaking, Mountain biking, Rowing, Gardening, Water sports, role-playing games

Introduction: My name is Fredrick Kertzmann, I am a gleaming, encouraging, inexpensive, thankful, tender, quaint, precious person who loves writing and wants to share my knowledge and understanding with you.