The script below will extract the last password changed date for all user objects in the domain in which the script is run. The output is the user’s DN, last password changed date, and the EmployeeID of the user in a tab delimited format.
I find that using the last password change date is more accurate in detecting dormant accounts than relying on the last login date. Last login is not replicated among DCs, and not all login types get recorded.
If your password policy is to expire after 90 days, sorting the output from this script for dates greater than 90 days will reveal which accounts have expired passwords. If the password has been in the expired state for 15 to 30 days, its pretty likely the account is dormant.
The script does have some code for extracting the last logon date, but I found the information was not trustworthy so I don’t dump it in the output.
To dump the results to a file use the following format:
cscript script-name.vbs >outputfile.txt
To make the sorting easier in Excel, you can use some simple text manipulation to change the date to YYYY-MM-DD format (English, Canada). You can also use some simple text to column transformations to break down your OU structre into different columns. Depending on your OU structure, this may allow you to easily sort users by business unit, location, or other means.
—–
Option Explicit
Const E_ADS_PROPERTY_NOT_FOUND = &H8000500D
Dim objConnection, objCommand
Dim objRootDSE, strUserDNSDomain, strFilter, strQuery, objRecordSet
Dim strUserDN, k, objUser
Dim objsd, lngFlag, dtmvalue, objdse, datlastlogin
Dim objRootDSE, strUserDNSDomain, strFilter, strQuery, objRecordSet
Dim strUserDN, k, objUser
Dim objsd, lngFlag, dtmvalue, objdse, datlastlogin
on error resume next
‘ Use ADO to search the domain for all users
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOOBject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOOBject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
‘ Determine the DNS domain from the RootDSE object
Set objRootDSE = GetObject("LDAP://RootDSE")
strUserDNSDomain = objRootDSE.Get("DefaultNamingContext")
strUserDNSDomain = objRootDSE.Get("DefaultNamingContext")
‘ Filter to retrieve all user objects.
strFilter = "(&(objectCategory=person)(objectClass=user))"
strFilter = "(&(objectCategory=person)(objectClass=user))"
strQuery = "<LDAP://" & strUserDNSDomain & ">;" & strFilter _
& ";distinguishedName"
& ";distinguishedName"
objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 180
objCommand.Properties("Cache Results") = False
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 180
objCommand.Properties("Cache Results") = False
‘ Print headers in the output
WScript.Echo "DN" & vbtab & "PWD Set" & vbtab & "Last Login" & vbtab & "EmployeeID"
‘ Enumerate all users as distinguised names
Set objRecordSet = objCommand.Execute
Do Until objRecordSet.EOF
strUserDN = objRecordSet.Fields("distinguishedName")
Do Until objRecordSet.EOF
strUserDN = objRecordSet.Fields("distinguishedName")
Set objUser = GetObject("LDAP://" & strUserDN )
‘datLastLogin = objUser.Get("LastLogin")
‘Set objSD = objUser.Get("defaultNamingContext")
‘ Print the user’s DN and Password last set value
dtmValue = objUser.PasswordLastChanged
datlastlogin = objuser.lastlogin
datlastlogin = objuser.lastlogin
WScript.Echo StrUserDN & vbtab & dtmValue & vbtab & datlastlogin & vbtab & objUser.EmployeeID
objRecordSet.MoveNext
Loop
‘ Variable Clean up
objConnection.Close
Set objConnection = Nothing
Set objCommand = Nothing
Set objRootDSE = Nothing
Set objRecordSet = Nothing
Set objConnection = Nothing
Set objCommand = Nothing
Set objRootDSE = Nothing
Set objRecordSet = Nothing