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 more convenient to use PowerShell to parse and analyze information from the event log. In this article, you will learn how to use Get-WinEvent cmdlet to retrieve information from the Windows event log.
Get-WinEvent: Search the Event Log Using PowerShell
To use the Get-WinEvent command, you must be running PowerShell as an administrator. If you try to run Get-WinEvent as a non-administrator user, you will not be able to access some logs, including the Security log.
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
The most common logs to query are the System, Application, Security, or Setup logs. You can also specify other log names. You can get a complete list of event logs in Windows with the command:
Get-WinEvent -ListLog *
For example, to view the RDP connection history on a computer, you would specify Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
log:
Get-WinEvent -LogName Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational
Or you can get the SSH connection log from OpenSSH/Operational Log in Windows:
Get-WinEvent -LogName OpenSSH/Operational
You can also select events from multiple logs at once. For example, if you want to retrieve information about errors and warnings from the 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 )}
you can use select-object or Format-Table cmdlets to display only specific event fields:
Get-WinEvent -LogName System | Format-Table Machinename, TimeCreated, Id, UserID
You can further process the data obtained from the event log. In this example, we’ll quickly convert the username to a SID:
Get-WinEvent -filterhash @{Logname="system"} |
Select-Object @{Name="Computername";Expression = {$_.machinename}},@{Name="UserName";Expression = {$_.UserId.translate([System.Security.Principal.NTAccount]).value}}, TimeCreated
Faster event search with filter hashtable option
The above method of filtering specific events from the Event Viewer log with the Where-Object may be easier to understand, but it is extremely slow, especially if you want to search through a large number of events. In most cases, it is better to use the Event Viewer server-side filtering by using filter hashtable Option.
Now, let’s try to generate a list of errors and warnings over a 30-day period using a warehousing object and a 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
Same command with filtered hashtable:
(Measure-Command {Get-WinEvent -FilterHashtable @{LogName="System",'Application'; Level =2,3; StartTime=$StartDate }}).TotalMilliseconds
This example shows filter hashtable event filtering command 30 times faster ware-object filter over normal ( 2.5
sec vs 76
seconds).
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
The Filter Hashtable argument allows you to filter by the following event attributes:
- logname
- provider name
- path
- keyword (use 9007199254740992 to discover successful events and 4503599627370496 for losers)
- Identification
- level (1=fatal, 2=error, 3=warning, 4=info, 5=debug, 6=trace, 0=info)
- start time
- end time
- UserID (SID of the user)
- statistics
Here’s an example of finding an event in a given time period:
Get-WinEvent -FilterHashTable @{LogName="System"; StartTime=(get-date).AddDays(-7); EndTime=(get-date).AddHours(-1); ID=1234}
If you want to find specific text in event description then below command can be used:
Get-WinEvent -FilterHashtable @{logname="System"}|Where {$_.Message -like "*USB*"}
Advanced Get-WinEvent Filtering with FilterXML
The FilterHashtable option has some limitations with the Get-WinEvent filter. If you need to use complex queries with multiple criteria to select events, you need to use FilterXML Flag, which allows you to select using an XML query. Similar to FilterHashtable, FilterXML filters are server-side. This means that you get the result very quickly.
For example, another way to get the latest errors from the system log for the last 30 days is:
$xmlQuery = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[(Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) <= 2592000000]]]</Select>
</Query>
</QueryList>
'@
Get-WinEvent -FilterXML $xmlQuery
To generate a complex XML query code, you can use the Event Viewer graphical console:
- run command
eventvwr.msc
, - Find the log for which you want to create a query and click Filter Current Log,
- Select the required query parameters in the Filter form. In this example, I want to find events with a specific event ID for the last 7 days for a specific user;
- To get the XML query code, go to the XML tab, and copy the XPath code (
CTRL+A
,CTRL+C
, - You can manually edit this query 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
Receive event logs from remote computers
To receive events from a remote computer, just specify its name -computer name Parameters:
$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 list of remote computers from 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’s 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}
}
Leave a Comment