Thursday, August 23, 2012

Find Inactive Users using Powershell

This is a quick hitter that came about when I was chatting with a few friends online.   We were talking about finding inactive users using powershell.   We also wanted to output their userid(samaccountname) and their last logon time.

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.113556.1.4.803:=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:""

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.