Total events found - powershell

I'm developing a script where I look for specific windows events. I would like the script to display the total of events found at the end of the script.
Get-WinEvent -FilterHashtable #{
LogName='Application'
Level= 4
StartTime=(Get-Date).AddHours(-24)
}

As Lee has pointed out in the comments, the two easiest ways to go about this would be:
$var = Get-WinEvent -FilterHashtable #{
LogName='Application'
Level= 4
StartTime=(Get-Date).AddHours(-24)
}
$var.Count
and
(Get-WinEvent -FilterHashtable #{
LogName='Application'
Level= 4
StartTime=(Get-Date).AddHours(-24)
}).Count

Related

Advanced Event Viewer filters

Exist the possibility to extract some information from Event viewer about event id description via powershell?
For example i want to see if I have on domain controller this event id 4776 with description "Authentication Package: WDigest".
You can use Get-WinEvent's -FilterXPath parameter to very granularly filter against the raw event xml.
In your case we could find all WDigest auth events with:
Get-WinEvent -FilterXPath "*[System[EventID=4776] and EventData[Data[#Name='PackageName']='WDigest']]" -LogName "Security"
It would be easier with the logname or providername, but it's possible to search all the logs, unlike in the event viewer. You can't just say '*' for the logname, because of a 256 logname query limit in the windows api:
get-winevent -listlog * |
foreach {
get-winevent #{ logname = $_.logname; id = 4776 } -ea 0 } |
where message -match 'Authentication Package: WDigest'
In powershell 6 or 7 you can filter on named eventdata:
get-winevent #{ Logname = 'Security'; ID = 4776; PackageName = 'WDigest' }
In powershell 5 maybe this. Data can't have wildcards.
get-winevent #{ Logname = 'Security'; ID = 4776; Data = 'WDigest' }

powershell get-eventlog add if more than 5 times

I am using:
"%windir%\system32\WindowsPowerShell\v1.0\powershell.exe" $log=Get-EventLog -LogName Security -InstanceID 4625 -After (Get-Date).AddDays(-60); if (($log)) {Write-Output $log[0].Message} ELSE {Write-Output 'WARNING-NoEventFound'}
This works perfect for me. I want to expand if possible and say write the output if the event happened more than 5 times. Similar to:
Count(*) > 5 that I would use in SQL.
I'd like to mention an alternative to Get-EventLog: Get-WinEvent
It usually has a lot better performance, both locally and over the network, it can do server side filtering with -FilterHashTable before sending the results. This can come in handy since Active Directory logs can be quite large sometimes.
Since you're only interested in if it's >5 results or not, we can also speed it up by breaking early when we have found 6 results, using -MaxEvents, and then just check whether we found 6 events or not.
$maxEvents = 6
$filterHashtable = #{
LogName = 'Security'
Id = 4625
StartTime = (Get-Date).AddDays(-60)
}
$log = Get-WinEvent -FilterHashtable $filterHashtable -MaxEvents $maxEvents
if ($log.Count -ge $maxEvents) {
#your code here
For readability I prefer to have the hashtable in a variable, but it can also be written inline like this, with ; as separator for the key value pairs:
Get-WinEvent -FilterHashtable #{ LogName = 'Security'; Id = ... }

Why do I get different results with Get-WinEvent versus Get-EventLog?

I'm trying to use Get-WinEvent to retrieve events from the eventlog for specific provider names that my company uses to write to the eventlog. I'm finding that I'm getting differing results depending on whether I use Get-WinEvent versus Get-EventLog, and I'm not sure why.
Using this test code (both provider names are proprietary names for different applications my company has):
$pName1 = "MagicFS6"
$pName2 = "MT_WPLAppServer"
$provider = $pName2
$fhash = #{
logname = 'application';
providername = $provider;
StartTime = '8/1/2017 12:00:00 AM'
}
$fhashevent = $null
$fhashevent = Get-WinEvent -FilterHashtable $fhash
$count = $fhashevent.Count
Write-Host "$provider had $count events using Get-WinEvent"
$eventlog = Get-EventLog -LogName Application -Source $provider -After '8/1/2017 12:00:00 AM'
$count = $eventlog.Count
Write-Host "$provider had $count events using Get-EventLog"
Running with $pName1 (MagicFS6), both Get-WinEvent and Get-EventLog return the same number of events. This tells me that the code is equivalent.
However, running with $pName2 (MT_WPLAppServer), Get-WinEvent returns 0 events, and Get-EventLog correctly returns thousands of results.
MagicFS6 had 12662 events using Get-WinEvent
MagicFS6 had 12662 events using Get-EventLog
MT_WPLAppServer had 0 events using Get-WinEvent
MT_WPLAppServer had 11483 events using Get-EventLog
For my needs, I need to use Get-WinEvent, so I would love some ideas on why this is not returning reliable results.

Get events from yesterday

I am trying to use PowerShell to get the results from the TaskScheduler events since yesterday. This is my code:
Get-WinEvent -LogName Microsoft-Windows-TaskScheduler/Operational -MaxEvents 5 |
Where-Object ($_.TimeCreated -gt [DateTime]::Today.AddDays(-1))
Format-List *
Notes:
The -MaxEvents 5 is to limit output while I am developing.
When I remove the Where-object the cmdlet returns a full list. This is expected since no filtering is applied. So the error must be in the way the filtering is being done.
You can use the FilterHashTable property of Get-WinEvent to filter, it will be faster than retrieving all the events and then filtering only those you want.
This retrieves all events in the last day from the System log as I don't have any logging for TaskScheduler.
$date = (Get-Date).AddDays(-1)
$events = Get-WinEvent -FilterHashTable #{ LogName = "System"; StartTime = $date;}
$events | Format-List
You can filter on pretty much any field in the event log - further info on this

Powershell, -filterhashtable, and operators

I'm filtering event log entries using the "Get-Winevent" cmdlet. I want to get events whose levels are less than 4 (or where LevelName isn't "Informational").
I use the -filterhashtable flag to filter the events. But is there a way to do comparisons with filterhashtable? Or just put a "not"? Or does filterhashtable only accept "=" as an operator?
These two snippets work and get the same results:
where-object
$events = Get-WinEvent -computer ServerName -LogName System | Where-Object {$_.level -lt 4}
-filterhashtable
$events = Get-WinEvent -computer ServerName -FilterHashTable #{LogName = 'System'; Level = 1}
$events += Get-WinEvent -computer ServerName -FilterHashTable #{LogName = 'System'; Level = 2}
$events += Get-WinEvent -computer ServerName -FilterHashTable #{LogName = 'System'; Level = 3}
The second snippet runs much faster than the first snippet (2 minutes versus 16 seconds in one case). As I understand it, "where-object" has to wait until "Get-WinEvent" has gotten every event object (possibly thousands). Adding "-filterhashtable" causes the target system's event log to filter before it gives the event object ot Get-WinEvent, which is much faster.
Can I combine the statements? These snippets don't work:
$events = Get-WinEvent -computer ServerName -FilterHashTable #{LogName = 'System'; Level < 4}
$events = Get-WinEvent -computer ServerName -FilterHashTable #{LogName = 'System'; Level != 2}
The "Level" properties is type "int[32]" so a comparison operator should work. In fact, it does work with "where-object". But it doesn't work with the "-filterhashtable" flag. Is there no way to do that sort of comparison? Is "=" the only operator -filterhashtable accepts?
No dice on operators like that. The FilterXPath parameter supports that. However the help on the FilterHashtable parameter indicates it takes an array of int, so it would accept:
... -FilterHashtable #{LogName='System';Level=0,1,3}
No, you cant. A hashtable is a collection of key = value pairs, so it won't allow relational operators.
Btw, in Powershell < is -lt and > is -gt.