Scroll Top
Evotec Services sp. z o.o., ul. Drozdów 6, Mikołów, 43-190, Poland

PSEventViewer – PowerShell Module

Following PowerShell Module provides basic functionality of working with Windows Event Logs.

Note worthy features
Easily list different types of Windows Events
Advanced Event Parsing in simple way
Runspaces allowing you to run code in parallel
Automatic splitting of number of events in 22 chunks
Automatic conversion of hidden data into variables
Keywords and Levels in their prettified form
Useful links
Code is published on GitHub
Issues should be reported on GitHub
Code is published as a module on PowerShellGallery
Installing module from PowerShellGallery

While you can use the script in a standard way by downloading it from GitHub, putting it in right places and getting it to run…there is much simpler way. Since the script was published to PowerShell Gallery you can simply install the module and run it from anywhere. Just use Install-Module PSEventViewer.

Install-Module -Name PSEventViewer 

If you ever need to update it…

Update-Module -Name PSEventViewer 
Why would I use PSEventViewer

That's a very fair question… why would I use PSEventViewer (Get-Events) instead of simply relying on Get-WinEvent that comes built-in. Well PSEventViewer is actually a wrapper around Get-WinEvent. But it has at least 3 more features you get for free that are better then original. That is… runspaces,  splitting Event ID's into chunks, and converting XML data into variables. The first option gives you parallel reading of event logs (think how it impacts your search over 2,5,10 servers if you do them one by one). Second option overcomes Windows limit which is a limit of 22 event id's that can be asked with one query (you get empty results on 23 and more). Third option gives you much easier  reading of additional, hidden data. Think how hard it is to get data from Message…

If you're browsing for events via Event Viewer it's a pretty obvious one. Administrator did clear Security Log. But how would you do it via PowerShell?

Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 1102 } -ComputerName 'AD1' | Format-List *

So you get all the output, almost like you get it when using Event Viewer. Where is the problem? All that text regarding Who/When is stored as one text, ‘Message.' This text changes from event to event, and parsing gets tricky. This is where the Get-Events (PSEventViewer) function comes to play.

Import-Module PSEventViewer -Force
Get-Events -LogName 'Security' -Id 1102 -ComputerName 'AD1' | Format-List *

Notice this the difference? All the values you cared about that were stored as Message, are now also stored as variables on the Event. Nifty ha?

Basic examples for PSEventViewer

Basic functionality of this module is ability to quickly work thru events.

Import-Module PSEventViewer -Force
Clear-Host

# Define dates
$DateFrom = (get-date).AddHours(-11)
$DateTo = (get-date).AddHours(1)

$IDRequiringSplitOver23 = 1102, 5136, 5137, 5141, 4364, 4647, 4672, 4727, 4730, 4731, 4734, 4759, 4760, 4754, 4758, 4728, 4729, 4732, 4733, 4756, 4757, 4761, 4762, 4725, 4722, 4725, 4767, 4723, 4724, 4726, 4740, 4720, 4738
$IDNotRequiringSplit = 1102, 5136, 5137, 5141, 4364, 4647, 4672, 4727, 4730, 4731, 4734, 4759, 4760, 4754, 4758, 4728, 4729, 4732, 4733, 4756
$ID = 916

$TestServers = 'AD1.ad.evotec.xyz'

Get-Events -DateFrom $DateFrom -DateTo $DateTo -EventId $id -LogType 'Application' -Verbose -maxevents 5 # | fl *
Get-Events -DateFrom $DateFrom -DateTo $DateTo -EventId 916 -LogType 'Application' -MaxEvents 10 -Verbose
Get-Events -EventId 916 -LogType 'Application' -MaxEvents 10 -Verbose
Get-Events -Id $ID -LogName 'Security' -DateFrom $DateFrom -DateTo $DateTo -Verbose

$TestEvents0 = Get-Events -DateFrom $DateFrom -DateTo $DateTo -EventId $id -LogType 'Application' -Verbose -Maxevents 5 -Oldest
$TestEvents0 | Select-Object Computer, TimeCreated, Id, LevelDisplayName, Message | Format-Table -AutoSize

$TestEvents1 = Get-Events -Machine $TestServers -Id $IDNotRequiringSplit -LogName 'Security' -DateFrom $DateFrom -DateTo $DateTo -Verbose
$TestEvents1 | Select-Object Computer, TimeCreated, Id, LevelDisplayName, Message | Format-Table -AutoSize

$TestEvents2 = Get-Events -Machine $TestServers -Id $IDRequiringSplitOver23 -LogName 'Security' -DateFrom $DateFrom -DateTo $DateTo -Verbose
$TestEvents2 | Select-Object Computer, TimeCreated, Id, LevelDisplayName, Message | Format-Table -AutoSize

$ID = 4768 #, 4722, 4723, 4724, 4725, 4726, 4738, 4740, 4767
$TestEvents3 = Get-Events -Machine $TestServers -Id $ID -LogName 'Security' -MaxEvents 2000 -Verbose # -DisableParallel
$TestEvents3 | Select-Object Computer, TimeCreated, Id, LevelDisplayName, Message | Format-Table -AutoSize

For the verification process of how module handles different type of events following code was used

Import-Module PSEventViewer -Force
Clear-Host
Write-Color 'Start processing events - Tests for expected output' -Color Red
# #, 4722, 4723, 4724, 4725, 4726, 4738, 4740, 4767
$TestServers = 'AD1.ad.evotec.xyz'
$ID = 104
$TestEvents1 = Get-Events -Machine $TestServers -Id $ID -LogName 'System' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 16384
$TestEvents2 = Get-Events -Machine $TestServers -Id $ID -LogName 'Application' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 4634
$TestEvents3 = Get-Events -Machine $TestServers -Id $ID -LogName 'Security' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 4688
$TestEvents4 = Get-Events -Machine $TestServers -Id $ID -LogName 'Security' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 105
$TestEvents5 = Get-Events -Machine $TestServers -Id $ID -LogName 'Application' -MaxEvents 1  #-DisableParallel  #-Verbose
$ID = 7036
$TestEvents6 = Get-Events -Machine $TestServers -Id $ID -LogName 'System' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 32
$TestEvents7 = Get-Events -Machine $TestServers -Id $ID -LogName 'System' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 1014
$TestEvents8 = Get-Events -Machine $TestServers -Id $ID -LogName 'System' -MaxEvents 1 #-DisableParallel #-Verbose
$ID = 8198
$TestEvents9 = Get-Events -Machine $TestServers -Id $ID -LogName 'Application' -MaxEvents 1  #-DisableParallel  #-Verbose
$ID = 10154
$TestEvents10 = Get-Events -Machine $TestServers -Id $ID -LogName 'System' -MaxEvents 1 #-DisableParallel #-Verbose

Write-Color 'Jump 1' -Color Green
$TestEvents1 | fl Channel, BackupPath, SubjectDomainName, SubjectUserName
Write-Color 'Jump 2' -Color Yellow
$TestEvents2 | fl NoNameA0, NoNameA1
Write-Color 'Jump 3' -Color Green
$TestEvents3 | fl TargetUserName, TargetDomainName, TargetUserSid
Write-Color 'Jump 4' -Color Green
$TestEvents4 | fl Computer, SubjectUserSid, NewProcessName, ParentProcessName
Write-Color 'Jump 5' -Color Green
$TestEvents5 | fl NoNameA0, NoNameA1, NoNameA2
Write-Color 'Jump 6' -Color Green
$TestEvents6 | fl param1, param2
Write-Color 'Jump 7' -Color Green
$TestEvents7 | fl NoNameB1, NoNameB2
Write-Color 'Jump 8' -Color Green
$TestEvents8 | fl QueryName, AddressLength
Write-Color 'Jump 9' -Color Green
$TestEvents9 | fl NoNameA0, NoNameA1
Write-Color 'Jump 10' -Color Green
$TestEvents10 | fl spn1, spn2
Write-Color 'End processing events - Tests for expected output' -Color Red

All the use cases and comparison with Get-WinEvent and Get-EventLog are provided as part of this large article I wrote recently.  Make sure you read it for a full overview. Also if you want to know when updates are out, or changes occur I would suggest monitoring project on GitHub as changes happen there first. This project is highly connected to PSWinReporting and new features are added when that project demands it.