From 6cb5bd6c96f7ee4b990ba6746e6e63b08725ed0f Mon Sep 17 00:00:00 2001 From: jessikitty Date: Fri, 30 Jan 2026 12:52:33 +1100 Subject: [PATCH] Add DisplayName lookup from AD --- Get-UserLastLogonComputer.ps1 | 53 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/Get-UserLastLogonComputer.ps1 b/Get-UserLastLogonComputer.ps1 index 92a3404..5722a6c 100644 --- a/Get-UserLastLogonComputer.ps1 +++ b/Get-UserLastLogonComputer.ps1 @@ -6,7 +6,7 @@ .DESCRIPTION Queries Domain Controller security event logs for logon events (4624) to determine which computer each user last authenticated from. - Resolves IP addresses to computer names for network logons. + Resolves IP addresses to computer names and looks up user display names. .PARAMETER OutputPath Path for the output CSV file. Defaults to current directory. @@ -14,11 +14,11 @@ .PARAMETER DaysBack Number of days of event logs to search. Default is 7. -.PARAMETER IncludeNetworkLogons - Include Type 3 (Network) logons. Default is true. +.PARAMETER ExcludeNetworkLogons + Exclude Type 3 (Network) logons. Default includes them. -.PARAMETER ResolveIPs - Attempt to resolve IP addresses to hostnames. Default is true. +.PARAMETER SkipIPResolve + Skip IP to hostname resolution. Faster but less useful. .EXAMPLE .\Get-UserLastLogonComputer.ps1 @@ -66,6 +66,8 @@ $StartDate = (Get-Date).AddDays(-$DaysBack) # Cache for IP to hostname resolution $IPCache = @{} +# Cache for user display names +$UserCache = @{} function Resolve-IPToHostname { param([string]$IP) @@ -74,20 +76,16 @@ function Resolve-IPToHostname { return $null } - # Check cache first if ($IPCache.ContainsKey($IP)) { return $IPCache[$IP] } try { - # Try DNS reverse lookup $hostname = [System.Net.Dns]::GetHostEntry($IP).HostName - # Extract just the computer name (before the domain) $computerName = ($hostname -split '\.')[0].ToUpper() $IPCache[$IP] = $computerName return $computerName } catch { - # Try querying AD for the IP try { $computer = Get-ADComputer -Filter "IPv4Address -eq '$IP'" -Properties Name -ErrorAction SilentlyContinue if ($computer) { @@ -101,6 +99,27 @@ function Resolve-IPToHostname { } } +function Get-UserDisplayName { + param([string]$Username, [string]$Domain) + + $UserKey = "$Domain\$Username" + + if ($UserCache.ContainsKey($UserKey)) { + return $UserCache[$UserKey] + } + + try { + $User = Get-ADUser -Identity $Username -Properties DisplayName -ErrorAction SilentlyContinue + if ($User -and $User.DisplayName) { + $UserCache[$UserKey] = $User.DisplayName + return $User.DisplayName + } + } catch {} + + $UserCache[$UserKey] = '' + return '' +} + try { Write-Host "Retrieving logon events from Security log..." -ForegroundColor Yellow @@ -128,7 +147,6 @@ try { $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' @@ -143,7 +161,7 @@ try { if ($Domain -in @('Window Manager', 'Font Driver Host', 'NT AUTHORITY')) { continue } if ([string]::IsNullOrWhiteSpace($Username)) { continue } - # Determine computer name - try WorkstationName first, then resolve IP + # Determine computer name $Computer = $null if (-not [string]::IsNullOrWhiteSpace($Workstation) -and $Workstation -ne '-') { $Computer = $Workstation.ToUpper() @@ -152,7 +170,6 @@ try { } if ([string]::IsNullOrWhiteSpace($Computer)) { - # Store IP if we couldn't resolve if (-not [string]::IsNullOrWhiteSpace($IPAddress) -and $IPAddress -ne '-') { $Computer = "[$IPAddress]" } else { @@ -168,6 +185,7 @@ try { $UserLogons[$UserKey] = [PSCustomObject]@{ Domain = $Domain Username = $Username + DisplayName = '' # Will populate after Computer = $Computer IPAddress = if ($IPAddress -and $IPAddress -ne '-') { $IPAddress } else { '' } LogonTime = $LogonTime @@ -183,6 +201,13 @@ try { } Write-Host "Processed $ProcessedCount matching logon events." -ForegroundColor Yellow + Write-Host "Looking up display names for $($UserLogons.Count) users..." -ForegroundColor Yellow + + # Populate display names + foreach ($Key in $UserLogons.Keys) { + $User = $UserLogons[$Key] + $User.DisplayName = Get-UserDisplayName -Username $User.Username -Domain $User.Domain + } $Results = $UserLogons.Values | Sort-Object Domain, Username @@ -192,7 +217,7 @@ try { } # Export to CSV - $Results | Select-Object Domain, Username, Computer, IPAddress, LogonTime, LogonType | + $Results | Select-Object Domain, Username, DisplayName, Computer, IPAddress, LogonTime, LogonType | Export-Csv -Path $CsvFile -NoTypeInformation -Encoding UTF8 Write-Host "`n===== Results =====" -ForegroundColor Green @@ -201,7 +226,7 @@ try { Write-Host "" # Display summary table - $Results | Format-Table Domain, Username, Computer, LogonTime, LogonType -AutoSize + $Results | Format-Table Domain, Username, DisplayName, Computer, LogonTime, LogonType -AutoSize } catch [System.Exception] { if ($_.Exception.Message -match "No events were found") {