Welcome to MSDN Blogs Sign in | Join | Help

Decrypt my World

Cryptography, Security, Debugging and more!

News

  • Any of my posts is supported under any Microsoft standard support program or service. They are provided "AS IS" without warranty of any kind, and confer no rights.

Where are my readers?

Locations of visitors to this page

Favorite Posts

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)

 

Posted: Thursday, March 12, 2009 11:05 AM by alejacma
Filed under: ,

Comments

revere said:

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

# March 13, 2009 4:15 AM

alejacma said:

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

# March 13, 2009 4:59 AM

Paul said:

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.

# September 11, 2009 3:02 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker