<< Back to Script Library
Show recent logoffs
Show user name, logon and logoff times of all users who have logged off, or been logged off, the selected computer(s) in the last x hours where x is an argument defaulting to 48. Useful to be able to spot if many users were logged off at a specific time.
Arguments:
Hours back to search - default is 48
User - optional user name to search for otherwise all users will be displayed
Arguments:
Hours back to search - default is 48
User - optional user name to search for otherwise all users will be displayed
The Script
Copy Script
Copied to clipboard
<#
Show logoffs from machine, sorted on most recent, from User Profile Service operational event log entries
@guyrleech 2018
#>
[datetime]$endDate = Get-Date
[int]$totalSessions = 0
[int]$hoursBack = 0
[string]$logName = 'Microsoft-Windows-User Profile Service/Operational'
[string]$user = $null
[int]$daysBefore = 7
[int]$outputWidth = 400
# Altering the size of the PS Buffer
$PSWindow = (Get-Host).UI.RawUI
$WideDimensions = $PSWindow.BufferSize
$WideDimensions.Width = $outputWidth
$PSWindow.BufferSize = $WideDimensions
if( $args.Count )
{
if( ! [string]::IsNullOrEmpty( $args[0] ) )
{
$hoursBack = $args[0]
}
if( $args.Count -ge 2 -and ! [string]::IsNullOrEmpty( $args[1] ) )
{
$user = $args[1]
}
}
[datetime]$startDate = if( ! $hoursBack )
{
$endDate.AddYears( -20 ) ## should be long enough!
}
else
{
$endDate.AddHours( -$hoursBack )
}
## we look further back so we stand a better chance of finding the corresponding logon
[array]$events = @( Get-WinEvent -FilterHashtable @{ LogName = $logName ; id = 1,4 ; StartTime=(Get-Date $startDate).AddDays( -$daysBefore ) ; EndTime=$endDate } -ErrorAction SilentlyContinue -Oldest )
[array]$results = @( For( [int]$index = 0 ; $events -and $index -lt $events.Count ; $index++ )
{
if( $events[ $index ].Id -eq 4 -and $events[ $index ].TimeCreated -ge $startDate ) ## logoff
{
$logoffEvent = $events[ $index ]
[string]$userName =
try
{
([Security.Principal.SecurityIdentifier]($logoffEvent.UserId)).Translate([Security.Principal.NTAccount]).Value
}
catch
{
## Write-Error "Failed to get user name for SID $($logonEvent.UserId)"
$logoffEvent.UserId
}
if( [string]::IsNullOrEmpty( $user ) -or $userName -match $user )
{
[int]$sessionId = -1
if( $logoffEvent.Message -match '(\d+)\.$' ) ## Finished processing user logoff notification on session 2.
{
$sessionId = $Matches[ 1 ]
}
if( $sessionId -le 0 )
{
Write-Error "Failed to get valid session id from text `"$($logoffEvent.Message)`""
}
$logonEvent = $null
if( $sessionId -gt 0 )
{
For( [int]$search = $index + 1 ; $search -ge 0 ; $search-- )
{
if( $events[ $search ].Id -eq 1 -and $events[ $search ].UserId -eq $logoffEvent.UserId )
{
if( $events[ $search ].Message -match '(\d+)\.$' ) ## Recieved user logon notification on session 2.
{
[int]$loggedOnSessionId = $Matches[ 1 ]
if( $loggedOnSessionId -eq $sessionId )
{
$logonEvent = $events[ $search ]
break
}
}
}
}
}
[pscustomobject][ordered]@{ 'UserName' = $userName ; 'Session Id' = $sessionId ; 'Logon Time' = if( $logonEvent ) { $logonEvent.TimeCreated } ; 'Logoff Time' = $logoffEvent.TimeCreated }
}
}
} )
[string]$output = if( $hoursBack )
{
" in last $hoursBack hours (since $(Get-Date $startDate -Format G))"
}
if( ! [string]::IsNullOrEmpty( $user ) )
{
$output += " for user $user"
}
if( $results -and $results.Count )
{
Write-Output ( "$($results.Count) session logoffs found" + $output )
$results | Sort 'Logoff Time' -Descending | Format-Table -AutoSize
}
else
{
Write-Output "No logoffs found at all"
}