diff --git a/Get-UserLastLogonComputer.ps1 b/Get-UserLastLogonComputer.ps1 index 6a5f7a9..eb0b346 100644 --- a/Get-UserLastLogonComputer.ps1 +++ b/Get-UserLastLogonComputer.ps1 @@ -50,52 +50,48 @@ Write-Host "" $StartDate = (Get-Date).AddDays(-$DaysBack) -# Build XPath filter for Event ID 4624 (Successful Logon) -$LogonTypeFilter = ($LogonTypes | ForEach-Object { "Data[@Name='LogonType']=$_" }) -join " or " -$XPath = @" -*[System[ - EventID=4624 - and TimeCreated[@SystemTime >= '$($StartDate.ToUniversalTime().ToString("o"))'] - ] - and EventData[ - ($LogonTypeFilter) - ] -] -"@ - try { Write-Host "Retrieving logon events from Security log..." -ForegroundColor Yellow - $Events = Get-WinEvent -LogName Security -FilterXPath $XPath -ErrorAction Stop | - Where-Object { - $xml = [xml]$_.ToXml() - $targetUser = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text' - $targetDomain = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text' - # Filter out computer accounts and system accounts - $targetUser -notmatch '\$$' -and - $targetUser -notin @('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE', 'DWM-1', 'DWM-2', 'UMFD-0', 'UMFD-1') -and - $targetDomain -ne 'Window Manager' -and - $targetDomain -ne 'Font Driver Host' - } - - Write-Host "Found $($Events.Count) logon events. Processing..." -ForegroundColor Yellow + # Use hashtable filter - more reliable than XPath for date filtering + $FilterHash = @{ + LogName = 'Security' + ID = 4624 + StartTime = $StartDate + } + + $Events = Get-WinEvent -FilterHashtable $FilterHash -ErrorAction Stop + + Write-Host "Found $($Events.Count) total 4624 events. Filtering..." -ForegroundColor Yellow $UserLogons = @{} + $ProcessedCount = 0 foreach ($Event in $Events) { $xml = [xml]$Event.ToXml() + $LogonType = [int]($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text' + + # Skip if not a logon type we want + if ($LogonType -notin $LogonTypes) { continue } + $Username = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text' $Domain = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text' $Workstation = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'WorkstationName' }).'#text' - $LogonType = ($xml.Event.EventData.Data | Where-Object { $_.Name -eq 'LogonType' }).'#text' $LogonTime = $Event.TimeCreated + # Filter out computer accounts and system accounts + if ($Username -match '\$$') { continue } + if ($Username -in @('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE', 'DWM-1', 'DWM-2', 'DWM-3', 'UMFD-0', 'UMFD-1', 'UMFD-2', 'ANONYMOUS LOGON', '-')) { continue } + if ($Domain -in @('Window Manager', 'Font Driver Host', 'NT AUTHORITY')) { continue } + if ([string]::IsNullOrWhiteSpace($Username)) { continue } + if ([string]::IsNullOrWhiteSpace($Workstation)) { $Workstation = "Unknown" } $UserKey = "$Domain\$Username" + $ProcessedCount++ # Keep only the most recent logon for each user if (-not $UserLogons.ContainsKey($UserKey) -or $LogonTime -gt $UserLogons[$UserKey].LogonTime) { @@ -108,16 +104,22 @@ try { 2 { "Interactive" } 10 { "RDP" } 11 { "Cached" } - default { $LogonType } + default { "Type $LogonType" } } } } } + Write-Host "Processed $ProcessedCount matching logon events." -ForegroundColor Yellow + $Results = $UserLogons.Values | Sort-Object Domain, Username if ($Results.Count -eq 0) { - Write-Host "`nNo user logon events found in the specified time period." -ForegroundColor Yellow + Write-Host "`nNo user logon events found matching criteria." -ForegroundColor Yellow + Write-Host "This could mean:" + Write-Host " - No interactive/RDP logons in the last $DaysBack days" + Write-Host " - Audit policy may not be logging logon events" + Write-Host " - Try increasing -DaysBack value" return } @@ -133,10 +135,19 @@ try { # Display summary table $Results | Format-Table -AutoSize -} catch [System.Diagnostics.Eventing.Reader.EventLogNotFoundException] { - Write-Host "`nError: Security event log not accessible. Ensure you're running on a DC with appropriate permissions." -ForegroundColor Red -} catch [System.UnauthorizedAccessException] { - Write-Host "`nError: Access denied. Run as Administrator with permissions to read Security logs." -ForegroundColor Red -} catch { - Write-Host "`nError: $($_.Exception.Message)" -ForegroundColor Red +} catch [System.Exception] { + if ($_.Exception.Message -match "No events were found") { + Write-Host "`nNo logon events (Event ID 4624) found in the last $DaysBack days." -ForegroundColor Yellow + Write-Host "`nPossible causes:" -ForegroundColor Cyan + Write-Host " 1. Audit policy not enabled - Run: auditpol /get /category:`"Logon/Logoff`"" + Write-Host " 2. Security log was cleared recently" + Write-Host " 3. Try a larger -DaysBack value" + Write-Host "" + Write-Host "To enable logon auditing:" -ForegroundColor Cyan + Write-Host " auditpol /set /subcategory:`"Logon`" /success:enable" + } elseif ($_.Exception.Message -match "Access is denied") { + Write-Host "`nError: Access denied. Run PowerShell as Administrator." -ForegroundColor Red + } else { + Write-Host "`nError: $($_.Exception.Message)" -ForegroundColor Red + } }