The graphical Event Viewer console (Eventvwr.msc) is usually used to check Windows logs. Event Viewer provides information on most system and security events. You can use PowerShell to search, filter, and parse a large number of events in Event Viewer.
PowerShell cmdlets for getting info from Event Viewer logs
There are two built-in PowerShell cmdlets available in Windows for getting information from Event Viewer logs:
- Get-Eventlog โ a simple, convenient, and fast cmdlet for getting information from standard Windows logs: Application, Security, System. However, it cannot be used to get events from the extended application and service logs in Event Viewer;
- Get-WinEvent โ provides a more universal way to search and filter events in any of the logs available in Event Viewer. In modern versions of Windows, this cmdlet is the preferred way to get and process event logs.
Note. Get-EventLog is available only in Windows PowerShell 5.1 and earlier. It is not supported in PowerShell 7+, where you should use Get-WinEvent instead.
Get names of available Windows logs
To get the names of available Windows logs, run the command:
Get-WinEvent -ListLog *
Note that modern Windows installations typically contain hundreds of event logs, with the exact number depending on installed roles, features, and apps. Each log is stored in a separate .EVTX file in the %SystemRoot%\System32\Winevt\Logs\ directory.

To display the last 10 events from a specific log, specify the name of the log in the –LogName parameter, and then run the command:
Get-WinEvent -LogName 'Microsoft-Windows-Windows Defender/Operational' -MaxEvents 10
Filter events by specified criteria with Where-Object
You can use the Where-Object cmdlet to filter received events by specified criteria. For example, you may need to find all of the Windows Defender events with an Event ID of 1002:
Get-WinEvent -LogName 'Microsoft-Windows-Windows Defender/Operational'| Where-Object ID -eq 1002
Common Security Event IDs for Troubleshooting and Auditing
When investigating authentication issues, account changes, or suspicious activity, you should take a look at the following Security log Event IDs as they are among the most commonly used:
| Event ID | Description |
|---|---|
| 4624 | Successful logon |
| 4625 | Failed logon |
| 4634 | Logoff |
| 4648 | Logon using explicit credentials |
| 4672 | Special privileges assigned to a logon |
| 4720 | User account created |
| 4726 | User account deleted |
| 4728 | User added to a security group |
| 4732 | User added to a local security group |
| 4740 | User account locked out |
| 4768 | Kerberos TGT request |
| 4769 | Kerberos service ticket request |
| 4771 | Kerberos pre-authentication failure |
The following query helps you to identify systems generating the highest number of failed logon attempts during the last 24 hours:
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4625
StartTime=(Get-Date).AddHours(-24)
} |
Group-Object MachineName |
Sort-Object Count -Descending As an example, you can find recent account lockout events using the command:
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4740
} In order to retrieve failed logon attempts, use the following command:
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4625
} These Event IDs are frequently used during AD troubleshooting, security investigations, and compliance audits.
Filtering with Get-WinEvent filters
However, if you have a large number of events, this method of filtering will be very slow. To search the log more quickly, you can use the following Get-WinEvent filters:
- -FilterXPath <String>
- -FilterXml <XmlDocument>
- -FilterHashtable <Hashtable[]>
For example, to get the same results as the previous command, you can use the following hash table query:
Get-WinEvent -FilterHashTable @{LogName='Microsoft-Windows-Windows Defender/Operational';ID='1002'} 
This log search command is many times faster than the previous one (with Where-Object filtering).
Hash table example
Example of a hash table to search for multiple event IDs for the last 7 days:
$date = (Get-Date).AddDays(-7)
$hash = @{
LogName='Security';
ProviderName='Microsoft-Windows-Security-Auditing';
ID=4723,4724,4740;
StartTime=$date
}
Get-WinEvent -FilterHashtable $hash Filtering Events by Time Range
One of the most common event log search scenarios is when you need to find events that occurred during a specific time period. In order to get all System log events from the last 24 hours:
Get-WinEvent -FilterHashtable @{
LogName='System'
StartTime=(Get-Date).AddHours(-24)
} 
In case you need to find Security events generated during the last hour, use the following command:
Get-WinEvent -FilterHashtable @{
LogName='Security'
StartTime=(Get-Date).AddHours(-1)
} To retrieve Application log events from the last 7 days, use the command below:
Get-WinEvent -FilterHashtable @{
LogName='Application'
StartTime=(Get-Date).AddDays(-7)
} You can also specify an end time to limit the search window:
Get-WinEvent -FilterHashtable @{
LogName='System'
StartTime=(Get-Date).AddDays(-7)
EndTime=(Get-Date).AddDays(-1)
} Keep in mind that using StartTime and EndTime in a FilterHashtable query is significantly faster than retrieving all events and filtering them later with Where-Object.
Create XPath filter template
You can create an XPath filter template to select events from the log using the graphical Event Viewer snap-in.
-
- Right-click on the required log name and select Filter Current Log;
- Configure filter parameters;

- Go to the XML tab. Copy the XPath query code that is generated for you;

- Paste the code into the $xmlQuery variable to run this query using PowerShell:
$xmlQuery = @'
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">*[System[(Level=1 or Level=2) and (EventID=2 or EventID=8194 or EventID=100 or EventID=264) and TimeCreated[timediff(@SystemTime) <= 604800000]]]</Select>
</Query>
</QueryList>
'@
Use XML query to select events
$Events= Get-WinEvent -FilterXML $xmlQuery
Parse EventData from Windows Events
Note that in many real-world cases, Event ID alone is not enough. You often need to extract additional info stored in the EventData section of an event (such as usernames, IP addresses, process names, or logon details).
In order to inspect the properties of an event, retrieve the event first and then view its Properties collection:
$event = Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4740
} -MaxEvents 1
$event.Properties The output contains the individual EventData fields recorded by the event provider.
View Event XML
To see the complete event structure, convert the event to XML using the following command:
$event = Get-WinEvent -LogName Security -MaxEvents 1
[xml]$event.ToXml()
This allows you to inspect all EventData elements and determine which fields are available for parsing.
Extract Specific EventData Values
As an example, let’s take a look at the following command. It extracts EventData values from the newest account lockout event (Event ID 4740):
$event = Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4740
} -MaxEvents 1
$event.Properties[0].Value
$event.Properties[1].Value Keep in mind that the property index varies depending on the Event ID and event provider.
Parse EventData by XML Field Name
Here is a more reliable method, you can access EventData fields by name:
$event = Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4740
} -MaxEvents 1
$xml = [xml]$event.ToXml()
$xml.Event.EventData.Data |
Select-Object Name,'#text' This method is easier to maintain because it does not depend on the position of properties in the event record.
Here is an example which retrieves the username from failed logon events (Event ID 4625):
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4625
} -MaxEvents 10 |
ForEach-Object {
$xml = [xml]$_.ToXml()
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
UserName = ($xml.Event.EventData.Data |
Where-Object {$_.Name -eq 'TargetUserName'}).'#text'
}
} Export the events found to CSV file
You can now export the events found to a CSV file:
$Events | Export-CSV "C:\Report\LastEvents.CSV" -NoTypeInformation -Encoding UTF8

Reading Archived EVTX Files with PowerShell
In addition to querying live Windows event logs, you can read archived .evtx files using Get-WinEvent. This is useful for incident response, security investigations, compliance audits, and troubleshooting historical events.
In order to display events from an exported log file, run the following command:
Get-WinEvent -Path "C:\Logs\Security.evtx"
To retrieve only the latest 50 events from the file, use the command below:
Get-WinEvent -Path "C:\Logs\Security.evtx" -MaxEvents 50
You can also filter events from an EVTX file using a hash table query:
Get-WinEvent -Path "C:\Logs\Security.evtx" |
Where-Object {$_.Id -eq 4625}
When working with large archived EVTX files, you need to avoid excessive Where-Object filtering whenever possible because all events must be loaded before PowerShell can process them:
Get-WinEvent -Path "C:\Logs\Security.evtx" -MaxEvents 1000 |
Select-Object TimeCreated, Id, Message
For better performance on large log files, you should use FilterXPath/FilterXml instead of filtering with Where-Object.
Here is an example to display failed logon events (Event ID 4625) stored in an archived Security log:
Get-WinEvent -Path "C:\Logs\Security.evtx" |
Where-Object {$_.Id -eq 4625} |
Select-Object TimeCreated, Id, ProviderName
This method is commonly used when analyzing exported logs from servers, workstations, or security appliances.
Get logs from remote PC using -ComputerName
You can get logs from a remote computer using the -ComputerName parameter. For example, the following PowerShell script can be used to search domain controllers for AD user account lockout events (Event ID 4740):
$DCs = "dc01","dc02","dc03"
foreach ($server in $DCs) {
Get-WinEvent -ComputerName $server `
-FilterHashtable @{
LogName='Security'
ID=4740
StartTime=(Get-Date).AddDays(-7)
}
}
Query Event Logs Through PowerShell Remoting
In modern enterprise environments, you can use PowerShell Remoting (WinRM) instead of the built-in **-ComputerName** parameter. This method allows you to run more complex event log queries and combine them with other admin tasks.
Here is an example:
Invoke-Command -ComputerName Server01 {
Get-WinEvent -LogName System -MaxEvents 50
} The following command allows collecting event logs from multiple servers in a single query using PowerShell Remoting:
$Servers = 'SRV1','SRV2','SRV3'
Invoke-Command -ComputerName $Servers {
Get-WinEvent -FilterHashtable @{
LogName='System'
StartTime=(Get-Date).AddHours(-24)
}
}
You can also create a persistent PowerShell session using the following construction:
$Session = New-PSSession -ComputerName Server01
Invoke-Command -Session $Session {
Get-WinEvent -FilterHashtable @{
LogName='Security'
ID=4740
StartTime=(Get-Date).AddDays(-7)
}
}
Remove-PSSession $Session
PowerShell Remoting is particularly useful when you are collecting logs from multiple servers, automating admin tasks, or working in environments where WinRM is already deployed for remote management.
In larger enterprise environments, you can centralize event collection using Windows Event Forwarding (WEF) or SIEM platforms such as Microsoft Sentinel. In these cases, Get-WinEvent is commonly used to query collected events from a central repository instead of individual machines.
Tip. You should always filter by time as early as possible when querying large Security logs. This can dramatically reduce query execution time and memory consumption.
What PowerShell cmdlets are used to read Event Viewer logs?
PowerShell provides two main cmdlets:
- Get-EventLog โ legacy cmdlet for standard logs (Application, System, Security)
- Get-WinEvent โ modern and recommended cmdlet that supports all event logs and advanced filtering
Which cmdlet should I use: Get-EventLog or Get-WinEvent?
You should use Get-WinEvent because:
- It works with all event logs (including advanced application logs)
- It is supported in PowerShell 7+
- It supports faster filtering methods like FilterHashtable
What are common Security Event IDs?
Commonly used Event IDs for troubleshooting and auditing include:
- 4624 โ Successful logon
- 4625 โ Failed logon
- 4634 โ Logoff
- 4648 โ Logon using explicit credentials
- 4672 โ Special privileges assigned
- 4720 โ User account created
- 4726 โ User account deleted
- 4740 โ Account locked out
- 4768 / 4769 โ Kerberos authentication events
Why is FilterHashtable recommended over Where-Object?
Because:
- Filtering happens at the source (log engine level)
- It significantly improves performance
- It reduces memory usage when processing large logs
What is the best practice when working with event logs?
- Always filter as early as possible (especially by time)
- Prefer Get-WinEvent over Get-EventLog
- Use FilterHashtable instead of Where-Object
- Limit log scope before processing large datasets
