Public/Get-WinslopFixLog.ps1
|
function Get-WinslopFixLog { <# .SYNOPSIS Retrieves WinslopFix event log entries with structured output. .DESCRIPTION Queries the Windows Application Event Log for entries written by the WinslopFix source. Returns structured objects with parsed metadata for easy filtering and pipeline consumption. Supports filtering by category (Kills, Errors, Lifecycle) and by date range. .PARAMETER Newest Maximum number of entries to return. Default: 50. .PARAMETER Category Filter by event category based on EventID ranges: - All: All events - Lifecycle: Guard start/stop/config (1000-1999) - Detection: Process detection events (2000-2999) - Kills: Process termination events (3000-3999) - Policy: AI feature changes (4000-4999) - Errors: Error events (9000-9999) .PARAMETER After Only return events generated after this datetime. .EXAMPLE Get-WinslopFixLog Returns the 50 most recent WinslopFix events. .EXAMPLE Get-WinslopFixLog -Category Kills -Newest 10 Returns the 10 most recent process termination events. .EXAMPLE Get-WinslopFixLog -After (Get-Date).AddHours(-1) Returns all events from the last hour. .OUTPUTS PSCustomObject[] .LINK https://github.com/DailenG/WinslopFix #> [CmdletBinding()] [OutputType([PSCustomObject[]])] param( [Parameter()] [ValidateRange(1, 1000)] [int]$Newest = 50, [Parameter()] [ValidateSet('All', 'Lifecycle', 'Detection', 'Kills', 'Policy', 'Errors')] [string]$Category = 'All', [Parameter()] [datetime]$After ) process { $source = 'WinslopFix' # Check if the source exists to avoid noisy errors if (-not [System.Diagnostics.EventLog]::SourceExists($source)) { Write-Warning "Event log source '$source' is not registered. No logs to display. Run Install-WinslopFix to register the source." return } try { $entries = Get-EventLog -LogName Application -Source $source ` -Newest ($Newest * 3) -ErrorAction Stop # Over-fetch to allow category filtering } catch { Write-Warning "Failed to query event log: $($_.Exception.Message)" return } # Apply date filter if ($PSBoundParameters.ContainsKey('After')) { $entries = $entries | Where-Object { $_.TimeGenerated -gt $After } } # Define category ranges $categoryRanges = @{ Lifecycle = @{ Min = 1000; Max = 1999 } Detection = @{ Min = 2000; Max = 2999 } Kills = @{ Min = 3000; Max = 3999 } Policy = @{ Min = 4000; Max = 4999 } Errors = @{ Min = 9000; Max = 9999 } } # Apply category filter if ($Category -ne 'All' -and $categoryRanges.ContainsKey($Category)) { $range = $categoryRanges[$Category] $entries = $entries | Where-Object { $_.EventID -ge $range.Min -and $_.EventID -le $range.Max } } # Take the requested count after filtering $entries = $entries | Select-Object -First $Newest # Return structured objects foreach ($entry in $entries) { $resolvedCategory = 'Unknown' foreach ($cat in $categoryRanges.Keys) { $r = $categoryRanges[$cat] if ($entry.EventID -ge $r.Min -and $entry.EventID -le $r.Max) { $resolvedCategory = $cat break } } [PSCustomObject]@{ PSTypeName = 'WinslopFix.LogEntry' Timestamp = $entry.TimeGenerated EventId = $entry.EventID Category = $resolvedCategory EntryType = $entry.EntryType.ToString() Message = $entry.Message } } } } |