Reputation: 1587
Suppose I want to find the newest occurrence of event 4688
that contains the string 0x1278
. I am able to find the event by getting a certain number of events and then searching the message for that string:
Get-WinEvent -MaxEvents 1000 -FilterHashTable @{LogName="Security";Id=4688} | Where-Object {$_.Message -match "0x1278"}
There are two issues with this approach:
Is there a way to address these issues? Ideally the event should be found in the shortest time possible.
Upvotes: 2
Views: 3162
Reputation: 174485
Use -FilterXPath
to offload filtering to the event log service!
This approach won't allow us to search the text of the rendered log message, but it will allow us to very granularly query structured data in the event.
Assuming that you're searching 0x1278
because it's a process ID event, we can query for that specific event with the following XPath expression:
*[System[EventID=4688] and EventData[Data[@Name='NewProcessId']='0x3e8']]
Used with Get-WinEvent
, we end up with something like:
Get-WinEvent -MaxEvents 1000 -FilterXPath "*[System[EventID=4688] and EventData[Data[@Name='NewProcessId']='0x3e8']]" -LogName "Security"
Now the eventlog service only needs to return one event, making your Get-WinEvent
query execute much faster
Upvotes: 2
Reputation: 1587
Instead of piping the array of events to Where-Object
, pipe it to ForEach-Object
, assign the first match to a variable, and then break out of the loop. If you remove the -MaxEvents
parameter, all events will be searched until a match is found or there are no more events:
PS C:\WINDOWS\system32> Get-WinEvent -FilterHashTable @{LogName="Security";id=4688} | ForEach-Object {if ($_.Message -match "0x1278") {$result = $_; break;}}
PS C:\WINDOWS\system32> $result
ProviderName: Microsoft-Windows-Security-Auditing
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
2/18/2020 10:14:55 AM 4688 Information A new process has been created....
Upvotes: 2