Add Get-UserLastLogonComputer.ps1 - exports users and last PC to CSV
This commit is contained in:
142
Get-UserLastLogonComputer.ps1
Normal file
142
Get-UserLastLogonComputer.ps1
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
#Requires -Modules ActiveDirectory
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Exports a list of users and the last PC they logged into.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
Queries Domain Controller security event logs for interactive logon events (4624)
|
||||||
|
to determine which computer each user last authenticated from.
|
||||||
|
|
||||||
|
.PARAMETER OutputPath
|
||||||
|
Path for the output CSV file. Defaults to current directory.
|
||||||
|
|
||||||
|
.PARAMETER DaysBack
|
||||||
|
Number of days of event logs to search. Default is 7.
|
||||||
|
|
||||||
|
.PARAMETER LogonTypes
|
||||||
|
Array of logon types to include. Default is 2 (Interactive) and 10 (RemoteInteractive/RDP).
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Get-UserLastLogonComputer.ps1
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\Get-UserLastLogonComputer.ps1 -OutputPath "C:\Reports" -DaysBack 30
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
Must be run on a Domain Controller with appropriate permissions to read Security logs.
|
||||||
|
Logon Type 2 = Interactive (console)
|
||||||
|
Logon Type 10 = RemoteInteractive (RDP)
|
||||||
|
Logon Type 11 = CachedInteractive
|
||||||
|
#>
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter()]
|
||||||
|
[string]$OutputPath = (Get-Location).Path,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[int]$DaysBack = 7,
|
||||||
|
|
||||||
|
[Parameter()]
|
||||||
|
[int[]]$LogonTypes = @(2, 10, 11)
|
||||||
|
)
|
||||||
|
|
||||||
|
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$CsvFile = Join-Path $OutputPath "UserLastLogonComputer_$Timestamp.csv"
|
||||||
|
|
||||||
|
Write-Host "`nQuerying security event logs for the last $DaysBack days..." -ForegroundColor Cyan
|
||||||
|
Write-Host "Looking for logon types: $($LogonTypes -join ', ')" -ForegroundColor Cyan
|
||||||
|
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
|
||||||
|
|
||||||
|
$UserLogons = @{}
|
||||||
|
|
||||||
|
foreach ($Event in $Events) {
|
||||||
|
$xml = [xml]$Event.ToXml()
|
||||||
|
|
||||||
|
$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
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Workstation)) {
|
||||||
|
$Workstation = "Unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
$UserKey = "$Domain\$Username"
|
||||||
|
|
||||||
|
# Keep only the most recent logon for each user
|
||||||
|
if (-not $UserLogons.ContainsKey($UserKey) -or $LogonTime -gt $UserLogons[$UserKey].LogonTime) {
|
||||||
|
$UserLogons[$UserKey] = [PSCustomObject]@{
|
||||||
|
Domain = $Domain
|
||||||
|
Username = $Username
|
||||||
|
Computer = $Workstation.ToUpper()
|
||||||
|
LogonTime = $LogonTime
|
||||||
|
LogonType = switch ($LogonType) {
|
||||||
|
2 { "Interactive" }
|
||||||
|
10 { "RDP" }
|
||||||
|
11 { "Cached" }
|
||||||
|
default { $LogonType }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Export to CSV
|
||||||
|
$Results | Select-Object Domain, Username, Computer, LogonTime, LogonType |
|
||||||
|
Export-Csv -Path $CsvFile -NoTypeInformation -Encoding UTF8
|
||||||
|
|
||||||
|
Write-Host "`n===== Results =====" -ForegroundColor Green
|
||||||
|
Write-Host "Total users found: $($Results.Count)"
|
||||||
|
Write-Host "Output saved to: $CsvFile"
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user