$Username = "JohnDoe"
$StartDate = [datetime]"2026-06-01 00:00:00"
$EndDate = [datetime]"2026-06-30 23:59:59"
$LogName = "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational"
$events = Get-WinEvent -FilterHashtable @{
LogName = $LogName
ID = @(21, 23, 24, 25)
StartTime = $StartDate
EndTime = $EndDate
} -ErrorAction SilentlyContinue |
Where-Object { $_.Message -match $Username } |
Sort-Object TimeCreated
$activeSessions = @{}
$rawResults = @()
foreach ($event in $events) {
$user = $event.Properties[0].Value
$sessionID = $event.Properties[1].Value
$ip = if ($event.Properties.Count -gt 2) { $event.Properties[2].Value } else { "N/A" }
switch ($event.Id) {
{ $_ -in 21, 25 } {
# Store the start time and IP
$activeSessions[$sessionID] = @{ LogonTime = $event.TimeCreated; IP = $ip }
}
{ $_ -in 23, 24 } {
# Match with the start time
$session = $activeSessions[$sessionID]
$logonTime = if ($session) { $session.LogonTime } else { $null }
$logoffTime = $event.TimeCreated
$durationStr = "N/A"
$totalMinutes = 0
# Calculate session duration
if ($logonTime) {
$ts = New-TimeSpan -Start $logonTime -End $logoffTime
$hours = [math]::Floor($ts.TotalHours)
$durationStr = "{0}h {1}m" -f $hours, $ts.Minutes
$totalMinutes = $ts.TotalMinutes
}
$rawResults += [PSCustomObject]@{
Username = $user
RemoteIP = if ($session) { $session.IP } else { $ip }
LogonTime = if ($logonTime) { $logonTime } else { "Prior to Timeframe" }
LogoffTime = $logoffTime
Duration = $durationStr
EndState = if ($_ -eq 23) { "Logged Off" } else { "Disconnected" }
_DateKey = $logoffTime.Date # Hidden property for grouping by day
_TotalMins = $totalMinutes # Hidden property for math
}
if ($session) { $activeSessions.Remove($sessionID) }
}
}
}
foreach ($key in $activeSessions.Keys) {
$rawResults += [PSCustomObject]@{
Username = $Username
RemoteIP = $activeSessions[$key].IP
LogonTime = $activeSessions[$key].LogonTime
LogoffTime = "Still Active"
Duration = "N/A"
EndState = "Active"
_DateKey = $activeSessions[$key].LogonTime.Date
_TotalMins = 0
}
}
$rawResults = $rawResults | Sort-Object LogonTime
$finalResults = @()
$grouped = $rawResults | Group-Object _DateKey
foreach ($group in $grouped) {
$items = $group.Group
# Calculate the total minutes for the day
$dailyTotalMins = ($items | Measure-Object _TotalMins -Sum).Sum
$dailyH = [math]::Floor($dailyTotalMins / 60)
$dailyM = [math]::Round($dailyTotalMins % 60)
$dailyTotalStr = "{0}h {1}m" -f $dailyH, $dailyM
for ($i = 0; $i -lt $items.Count; $i++) {
$item = $items[$i]
$isLast = ($i -eq ($items.Count - 1)) # Check if it's the last row of the day
$finalResults += [PSCustomObject]@{
Username = $item.Username
RemoteIP = $item.RemoteIP
LogonTime = $item.LogonTime
LogoffTime = $item.LogoffTime
Duration = $item.Duration
DailyTotal = if ($isLast) { $dailyTotalStr } else { "" }
EndState = $item.EndState
}
}
}
$finalResults | Format-Table -AutoSizeWas this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article