How to get LastLogon property for all users in a Domain (VBScript)


Hi all,


The following VBScript sample retrieves all users in Active Directory that haven’t ever logged on the domain, or haven’t logged on for at least maxDays (an argument passed to the script): 

On Error Resume Next

‘ Constants

Const ONE_HUNDRED_NANOSECOND = .000000100
Const SECONDS_IN_DAY = 86400

‘ Get Max Days as an argument passed to the script

If Not Wscript.Arguments.Count() = 1 Then
Wscript.Echo “Syntax error, argument required”
Wscript.Quit
End If

maxDays = CInt(Wscript.Arguments(0))

‘ Create the log file

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objLogFile = objFSO.CreateTextFile(GetPath() & “log.txt”, 8, true)

‘ Get the root of the domain

Set objRoot = Getobject(“LDAP://RootDSE”)
strRoot = objRoot.Get(“defaultnamingcontext”)
Set objRoot = Nothing

‘ Create connection

Set objConnection = CreateObject(“ADODB.Connection”)
objConnection.Open “Provider=ADsDSOObject;”

‘ Create command

Set objCommand = CreateObject(“ADODB.Command”)
objCommand.ActiveConnection = objConnection
objCommand.Properties(“Page Size”) = 1000

‘ Execute command to get all DCs in the domain

objCommand.CommandText = “<LDAP://OU=Domain Controllers,” & strRoot & “>;(objectcategory=computer);name;onelevel”
Set objRecordSet = objCommand.Execute

‘LogData(“INFO: There are ” & objRecordSet.RecordCount & ” Domain Controllers.”)

‘ Execute command to get all users in the domain

objCommand.CommandText = “<LDAP://” & strRoot & “>;(&(objectclass=user)(objectcategory=person));adspath,distinguishedname,sAMAccountName;subtree”
Set objRecordSet2 = objCommand.Execute

‘LogData(“INFO: There are ” & objRecordSet2.RecordCount & ” users.”)

‘ Get the LastLogon for each user in each DC

Do Until objRecordSet2.EOF

‘ Get the LastLogon for one user in each DC, and get the maximum

objRecordSet.MoveFirst
maxDate = 0
Do Until objRecordSet.EOF

‘ Execute command to get LastLogon for the user in one DC

LdapPath = “LDAP://” & objRecordSet.Fields(“name”).Value & “/” & Replace(objRecordSet2.Fields(“distinguishedname”).Value, “/”, “\/”)
set objUser = GetObject(LdapPath)

‘ Check for errors executing the command

if Err.Number <> 0 Then
‘ Error

LogData(“INFO: LDAP Path = ” & LdapPath)
Select Case Err.Number
Case &H8007203A
Err.Description = “””The server is not operational”””
Case &H80005000
Err.Description = “””An invalid ADSI pathname was passed”””
Case Else
Err.Description = “”
End Select
LogData(“ERROR: ” & Err.Number & ” ” & Err.Description)
Else
‘ No error

‘ Get the LastLogon

set objLastLogon = objUser.LastLogon
myDate = 0
If Not(IsNull(objLastLogon) Or IsEmpty(objLastLogon)) Then
myDate = MakeDate(objLastLogon)
End If

‘ See if it’s the maximum

If myDate > maxDate Then
maxDate = myDate
End If

End If

‘ Move on to the next DC

Err.Clear
set objUser = nothing
set objLastLogon = nothing
objRecordSet.MoveNext

Loop

‘ Show the maximum LastLogon for the user

If maxDate = 0 Then
LogData(“INFO: User “”” & objRecordSet2.Fields(“sAMAccountName”).Value & “”” never logged on.”)
ElseIf (Date() – maxDate) > maxDays Then
LogData(“INFO: User “”” & objRecordSet2.Fields(“sAMAccountName”).Value & “”” logged on ” & maxDate)
End If

‘ Move on to the next user

objRecordSet2.MoveNext

Loop

‘ Close everything

objRecordSet.Close
Set objRecordSet = Nothing
objRecordSet2.Close
Set objRecordSet2 = Nothing
Set objCommand = Nothing
objConnection.Close
Set objConnection = Nothing

‘ We are done!

Wscript.Echo “All Done!”

‘================================================================
‘ HELPER FUNCTIONS
‘================================================================

‘ Get script’s path

Function GetPath()

Dim path
path = WScript.ScriptFullName
GetPath = Left(path, InStrRev(path, “\”))

End Function

‘ Write data to log file

Sub LogData(data)

objLogFile.writeline Now() & “, ” & data

End Sub

‘ Convert long integer to a date

Function MakeDate(oLInt)

Set objShell = CreateObject(“Wscript.Shell”)

lngBiasKey = objShell.RegRead(“HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias”)

If UCase(TypeName(lngBiasKey)) = “LONG” Then
glngBias = lngBiasKey

ElseIf UCase(TypeName(lngBiasKey)) = “VARIANT()” Then
glngBias = 0

For k = 0 To UBound(lngBiasKey)
glngBias = lngBias + (lngBiasKey(k) * 256^k)
Next
End If

dtmDate = #1/1/1601# + (((oLInt.HighPart * (2 ^ 32)) + oLInt.LowPart) / 600000000 – glngBias) / 1440

MakeDate = dtmDate

End Function


 


I hope this helps.


Regards,


 


Alex (Alejandro Campos Magencio)


 

Comments (4)

  1. revere says:

    Many thanks for your answer, but all what I need is to get LastLoginInfo (Time and Date) for all users in only one OU in Domain. I can’t program in VBscript and can’t find any relevant tool in Windows 2000/2003. The previous script works the way I need, but it does’t display LastLogon Attribute. This one is too complicated for me to edit it and it is working for all users in AD. Could you please show me, how to modify previous script to show LastLogon information? When I added a line with requested attribute, it finished with runtime error Type Mishmatch. I think, that there is problem with data type, but I can’t to handle it. Thank you very much. Here is the script:

    Dim oLastLogon

    ‘ Get OU

    strOU = "OU=TEREZA,OU=PEOPLE,DC=FJFI,DC=CVUT,DC=CZ"

    ‘ Create connection to AD

    Set objConnection = CreateObject("ADODB.Connection")

    objConnection.Open "Provider=ADsDSOObject;"

    ‘ Create command

    Set objCommand = CreateObject("ADODB.Command")

    objCommand.ActiveConnection = objConnection

    objCommand.Properties("Page Size") = 1000

    ‘ Execute command to get all users in OU

    objCommand.CommandText = _

     "<LDAP://" & strOU & ">;" & _

     "(&(objectclass=user)(objectcategory=person));" & _

     "displayName,lastLogon,sAMAccountName;subtree"

    Set objRecordSet = objCommand.Execute

    ‘ Show info for each user in OU

    Do Until objRecordSet.EOF

     ‘ Show required info for a user

     ‘WScript.Echo objRecordSet.Fields("adspath").Value

     WScript.Echo objRecordSet.Fields("displayName").Value

     WScript.Echo objRecordSet.Fields("sAMAccountName").Value

     WScript.Echo objRecordSet.Fields("lastLogon").Value

     ‘ Move to the next user

     ‘

     objRecordSet.MoveNext

    Loop

    ‘ Clean up

    objRecordSet.Close

    Set objRecordSet = Nothing

    Set objCommand = Nothing

    objConnection.Close

    Set objConnection = Nothing

  2. alejacma says:

    LastLogon property is spread all over the DCs of the domain. You have to query the property in all DCs. You will need to mix both samples of mine. Unfortunately I cannot attend this kind of requests in the blog. Please, open a support case if you need help, and we will be more than happy to assist you.

    Regards,

    Alex

  3. Paul says:

    Actually beginning with Windows 2003 the lastLogon attribute is now replicated to all DCs.  You only need to query a single DC to get the last logon now.

  4. Tony says:

    FYI for anyone reading this:

    The lastLogon attribute is NOT replicated to all DCs for a 2003 domain functional level.  

    The new attribute introduced is called lastLogonTimestamp.  Find more info here (A MUST read):

    blogs.technet.com/…/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx