How do you find out when was the last time a particular user logged on?

(Get-QADUser username).lastLogon looks like an obvious answer but there are a few gotchas to be aware of.

The main of them: lastLogon attribute is actually not replicated between domain controllers so if you have more than one DC (which I am sure you do) you need to get it from all of them and get the latest of them.

Here’s the PowerShell code which does that:

Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName username).LastLogon
} | Measure-Latest

Basically, we are getting a list of all DCs in the company, then prompting each of them for the user’s lastLogon time, and then picking the latest of the values (I am using my Measure-Latest function – just copy/paste if before executing this command or put in your script.)

Note that there are utilities which can do that querying and comparison for you. NetWrix guys even have a PowerShell cmdlet described here, so you can do something like:

Get-NCInactiveUsers -domain example.com -days 15

You should also keep in mind that if your users do not log off and simply lock their workstations they do not log on either – Kuma is describing here how he has a script logging off users every night to avoid this.

Another alternative is using lastLogonTimeStamp attribute instead. This one does indeed get replicated. It was introduced in Windows 2003 (make sure your schema is 2003-level or later). But keep in mind that this one is not real-time as it is only replicated every 9-14 days.

So as long as you are looking for users who have not logged on for something bigger than 2 weeks you should be good using Shay’s script for locating inactive users:

$now=get-date
$daysSinceLastLogon=60

Get-QADUser -sizeLimit 0 | where {
  $_.lastlogontimestamp -and 
    (($now-$_.lastlogontimestamp).days -gt $daysSinceLastLogon)
} | Format-Table Name, LastLogonTimeStamp

Finally, you can speed things up considerably by constructing an LDAP query and thus doing all the filtering on the server side:

# calculate a deadline date. (now minus 60 days)
$deadline = (Get-Date).AddDays(-60).ToFileTimeUtc()

#construct a ldap query
$ldapQuery = '(|(!(lastLogonTimeStamp=*))(lastLogonTimeStamp<=' + $deadline + '))'

#run this query
Get-QADUser -Enabled -SizeLimit 0 -LdapFilter $ldapQuery
Advertisements