-
Notifications
You must be signed in to change notification settings - Fork 78
Description
I've been noticing that a lot (about 80%) of our computers do not have a last logged on user even though the scan is completing every time it runs.
So I began to do some testing on these computers that were scanning successfully but returning no data.
At first I thought that it was because of the "-newest 200" flag in the Get-EventLog cmdlet.
So I changed it to "-newest 2000" without any change in results.
Then I removed the "-newest" flag altogether to get all the events possible, but still no results.
I then moved my attention to the if statement below looking at the $LogonType variable.
This turned out to be the issue. There were no types matching "2", "10" or "11".
All we were getting were "3" and "5" types, and none of those were for the logged on user.
They were for the computer account, SYSTEM, and my remote PSSessions.
In a last-ditch effort to try and figure out a way to get some more data out of this scanner I turned to the currently logged in user.
I modified the script to check for the currently logged in user and if that was different that any of the users that were collected by the for loop above in the $UserArray variable. If there is a currently logged in user and it is not in that array then add it to the PSCustomObject to be returned with a logon type of "Current User" and the current timestamp for the last logon field.
Originally I was doing this check with a Get-CIMInstance cmdlet but it seemed to be failing for RDP and VDI users.
I then tried a few other options (WMI, owner of the explorer.exe process, etc) but they also did not work consistently.
Eventually I landed on the quser command and parsing the output of that which seems to be working well for me.
Here is my modified script:
# This script requires that Audit Logon events are enabled in Group Policy and those events are kept for the amount of history preferred
[CmdletBinding()]
param (
[Switch]$Lowercase
)
$UserArray = New-Object System.Collections.ArrayList
# Query all logon events with id 4624
Get-EventLog -LogName "Security" -Newest 200 -InstanceId 4624 -ErrorAction "SilentlyContinue" | ForEach-Object {
$EventMessage = $_
$AccountName = $EventMessage.ReplacementStrings[5]
$LogonType = $EventMessage.ReplacementStrings[8]
if ( $Lowercase ) {
# Make all usernames lowercase so they group properly in Inventory
$AccountName = $AccountName.ToLower()
}
# Look for events that contain local or remote logon events, while ignoring Windows service accounts
if ( ( $LogonType -in "2", "10", "11" ) -and ( $AccountName -notmatch "^(DWM|UMFD)-\d" -and ($AccountName -ne "") ) ) {
# Skip duplicate names
if ( $UserArray -notcontains $AccountName ) {
$null = $UserArray.Add($AccountName)
# Translate the Logon Type
if ( $LogonType -eq "2" ) {
$LogonTypeName = "Local"
}
elseif ( $LogonType -eq "10" ) {
$LogonTypeName = "Remote"
}
elseif ( $LogonType -eq "11" ) {
$LogonTypeName = "Cached"
}
$time = [DateTime]$EventMessage.TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss")
# Build an object containing the Username, Logon Type, and Last Logon time
[PSCustomObject]@{
Username = $AccountName
LogonType = $LogonTypeName
LastLogon = $time
}
}
}
}
# Get the current logged in user in case nothing is returned by the above
#$userName = (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty UserName).Split('\')[1]
$queryUser = quser
$userName = $null
if ($queryUser) {
$userName = $queryUser -match ' (\S+)\s+\d+ '
if ($matches) {
$userName = $matches[1]
}
}
# Return if no username found via quser
if ( $null -eq $userName ) {
return
}
$userName = $userName.Substring(1)
$userName = $userName.Split(" ")[0]
if ( $Lowercase ) {
# Make all usernames lowercase so they group properly in Inventory
$userName = $userName.ToLower()
}
if ($null -ne $userName -and $UserArray -notcontains $userName) {
[PSCustomObject]@{
Username = $userName
LogonType = "Current User"
LastLogon = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}