In this case the LastLogonTimeStamp attribute was good enough for this query. Note that this attribute is replicated but it is 9-14 days behind the current date
For full disclosure this is something I'd usually use oldcmp for but in this case the customer wasn't allowing third party tools.
The main problem I was having was the output of LastLogonTimeStamp via powershell. The date doesn't get automatically converted from its native 64 bit format. Luckily the Microsoft team has included the LastLogonDate which is the conversion of the LastLogonTimestamp. MVP Richard Mueller has a great explanation of the LastLogonDate attribute in Powershell It is important to emphasize that LastLogonDate is not an actual Active Directory attribute. LastLogonDate was key otherwise it makes this query more complex because we would have had to include a conversion into the command.
For the query I went with the search-adaccount cmdlet. We were looking for accounts that had not been active within 90 days
search-adaccount -usersonly -accountinactive -timespan "76" | select-object samaccountname, lastlogondate
If you want to export that to a CSV then that command can be piped into export-csv
search-adaccount -usersonly -accountinactive -timespan "76" | select-object samaccountname, lastlogondate | export-csv Users.csv
Why did I choose 76 instead of 90? That goes back to the DS blog about lastlogontimestamp being up to 14 days behind.
Active Directory Administrative Center also has some handy built-in searches that can help if you prefer a GUI
Update Good friend and Microsoft PFE Eric J suggested that I add a screenshot with the Windows 2012 version of ADAC and the powershell history viewer output. Great suggestion Eric!
The powershell command in the history viewer is interesting. I like the version above a lot better :)
Get-ADObject -LDAPFilter:"(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.1135126.96.36.1993:=2)(|(lastLogonTimestamp<=129888720000000000)(!lastLogonTimestamp=*)))" -Properties:allowedChildClassesEffective,allowedChildClasses,lastKnownParent,sAMAccountType,systemFlags,userAccountControl,displayName,description,whenChanged,location,managedBy,memberOf,primaryGroupID,objectSid,msDS-User-Account-Control-Computed,sAMAccountName,lastLogonTimestamp,lastLogoff,mail,accountExpires,msDS-PhoneticCompanyName,msDS-PhoneticDepartment,msDS-PhoneticDisplayName,msDS-PhoneticFirstName,msDS-PhoneticLastName,pwdLastSet,operatingSystem,operatingSystemServicePack,operatingSystemVersion,telephoneNumber,physicalDeliveryOfficeName,department,company,manager,dNSHostName,groupType,c,l,employeeID,givenName,sn,title,st,postalCode,managedBy,userPrincipalName,isDeleted,msDS-PasswordSettingsPrecedence -ResultPageSize:"100" -ResultSetSize:"20201" -SearchBase:"DC=MK2012,DC=com" -SearchScope:"Subtree" -Server:"w2012DC1.MK2012.com"
The issue I have with the ADAC method is that it doesn't allow the user to export the findings and include the LastLogonTimeStamp date in a converted form.
I'm looking forward to other suggestions comments on how to improve this powershell command. Remember we are talking quick-hitter one liner here.