Last domain logon for specific user

Author Message
harry

  • Total Posts : 10
  • Scores: 0
  • Reward points : 0
  • Joined: 9/14/2011
  • Status: offline
Last domain logon for specific user Thursday, September 15, 2011 6:00 PM (permalink)
0
Useful script for finding when a specified user last logged on to the domain.
I saw a similar script some time ago (it was for all domain users though), but I cannot remember where, so I wrote this one myself!
Any advice on making it better would be greatly appreciated!
 ' LastLogonSpecific.vbs 
' Script to check when a specific user last logged on to the domain. 
' As the LastLogon attribute does not replicate, each domain controller is 
' queried to find the latest LastLogon information for the specified user. 
' We could use the LastLogonTimeStamp attribute, which is replicated, but this 
' is inefficient as it only updates when the user logs on if the old value is 
' older than 14 days. 
'---------------------------------------------------------------------------' 
' As the lastLogon attribute does not get replicated, each DC in the domain 
' is queried to find the latest lastLogon for the specified user. 
' The latest date found is kept in a dictionary object. The script uses ADO 
' to search the domain for all DCs, and the AdsPath of each is saved into an 
' array. Then, for each DC, ADO is used to search AD on that DC for the user 
' object and return the lastLogon attribute. 
' The lastLogon attribute is a 64-bit number representing the number of 100 
' nanosecond intervals since 01/01/1991. This value is converted to a date. 
' The last logon date is in UTC, which must be adjusted by the Time Zone 
' bias, stored in the machine registry, to convert to local time. Option Explicit 
Dim adoCommand, adoConnection, adoRecordset, arrstrDCs(), dtmdate 
Dim k, lngBias, lngBiasKey, lngHigh, lngLow 
Dim objDate, objDC, objList, objRootDSE, objShell 
Dim strAttributes, strBase, strConfig, strDNSDomain 
Dim strFilter, strName, strNTName, strQuery strName = InputBox("Enter username","UserName","") ' Retrieve local Time Zone bias from registry 
Set objShell = CreateObject("Wscript.Shell") 
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _ 
    & "TimeZoneInformation\ActiveTimeBias") 
If (UCase(TypeName(lngBiasKey)) = "LONG") Then 
    lngBias = lngBiasKey 
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then 
    lngBias = 0 
    For k = 0 To UBound(lngBiasKey) 
        lngBias = lngBias + (lngBiasKey(k) * 256^k) 
    Next 
End If ' Use a dictionary object to track latest lastLogon for each user. 
Set objList = CreateObject("Scripting.Dictionary") 
objList.CompareMode = vbTextCompare ' Setup ADO objects and 
Set adoCommand = CreateObject("ADODB.Command") 
Set adoConnection = CreateObject("ADODB.Connection") 
adoConnection.Provider = "ADsDSOObject" 
adoConnection.Open "Active Directory Provider" 
adoCommand.ActiveConnection = adoConnection ' Identify domain controllers 
Set objRootDSE = GetObject("LDAP://RootDSE") 
strConfig = objRootDSE.Get("configurationNamingContext") 
strDNSDomain = objRootDSE.Get("defaultNamingContext") 
strBase = "<LDAP://" & strConfig & ">" 
strFilter = "(objectClass=nTDSDSA)" 
strAttributes = "AdsPath" 
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree" ' Run the query. 
adoCommand.CommandText = strQuery 
adoCommand.Properties("Page Size") = 100 
adoCommand.Properties("Timeout") = 60 
adoCommand.Properties("Cache Results") = False Set adoRecordset = adoCommand.Execute ' Enumerate parent objects of class nTDSDSA, save DC AdsPaths in arrstrDCs 
k = 0 
Do Until adoRecordset.EOF 
    Set objDC = _ 
        GetObject(GetObject(adoRecordset.Fields("AdsPath").Value).Parent) 
    ReDim Preserve arrstrDCs(k) 
    arrstrDCs(k) = objDC.DNSHostName 
    k = k + 1 
    adoRecordset.MoveNext 
Loop 
adoRecordset.Close strAttributes = "sAMAccountName,lastLogon" ' Retrieve lastLogon attribute for each user on each Domain Controller. 
For k = 0 To Ubound(arrstrDCs) 
    ' Search the entire domain in the copy of AD on this DC 
    strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">" 
    strFilter = "(|(sAMAccountName=" & strName & "))" ' Create LDAP syntax query and execute 
 strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree" 
 adoCommand.CommandText = strQuery 
 Set adoRecordset = adoCommand.Execute ' Enumerate the resulting recordset 
 Do Until adoRecordset.EOF 
  strNTName = adoRecordset.Fields("sAMAccountName").Value 
  On Error Resume Next 
  Set objDate = adoRecordset.Fields("lastLogon").Value 
  If (Err.Number <> 0) Then 
   On Error GoTo 0 
   dtmDate = #1/1/1991# 
  Else 
   On Error GoTo 0 
   lngHigh = objDate.HighPart 
   lngLow = objDate.LowPart 
   If (lngLow < 0) Then 
    lngHigh = lngHigh + 1 
   End If 
   If (lngHigh = 0) And (lngLow = 0) Then 
    dtmDate = #1/1/1991# 
   Else 
    dtmDate = #1/1/1991# + (((lngHigh * (2 ^ 32)) _ 
     + lngLow)/600000000 - lngBias)/1440 
   End If 
  End If ' Retain newest value for user 
  If (objList.Exists(strNTName) = True) Then 
     If (dtmDate > objList(strNTName)) Then 
    objList.Item(strNTName) = dtmDate 
   End If 
  Else 
   objList.Add strNTName, dtmDate 
  End If adoRecordset.MoveNext 
 Loop 
 adoRecordset.Close 
Next ' Output latest lastLogon date for specified user 
For Each strNTName In objList.Keys 
    Wscript.Echo strNTName & " last logged on at " & objList.Item(strNTName) 
Next adoConnection.Close 

I don't understand why the line breaks don't work properly, so if you want a copy of the code (with the correct line breaks!) just PM me
 
~harry
<message edited by harry on Thursday, September 15, 2011 6:03 PM>
 
#1
    59cobalt

    • Total Posts : 975
    • Scores: 91
    • Reward points : 0
    • Joined: 7/17/2011
    • Status: offline
    Re:Last domain logon for specific user Thursday, September 15, 2011 8:29 PM (permalink)
    0
    harry
    strAttributes = "sAMAccountName,lastLogon"
    ' Retrieve lastLogon attribute for each user on each Domain Controller. 
    For k = 0 To Ubound(arrstrDCs) 
     ' Search the entire domain in the copy of AD on this DC 
     strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
    Why would you want to do that? With Windows Server 2003 a new attribute lastLogonTimestamp was introduced that is replicated across domain controllers. And since Windows 2000 reached EoL in July 2010 you really don't want to use earlier versions anyway.

    harry
    strFilter = "(|(sAMAccountName=" & strName & "))"
    Using a more specific filter will speed up the query:
    strFilter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=" & strName & "))"

    harry
    strNTName = adoRecordset.Fields("sAMAccountName").Value
    Reading sAMAccountName is utterly pointless when you already used the sAMAccountName as a filter in your query. You'd be wasting resources on obtaining information that you already have.

    harry
    I don't understand why the line breaks don't work properly
    That's because the forum software sucks. Big time.
     
    #2
      harry

      • Total Posts : 10
      • Scores: 0
      • Reward points : 0
      • Joined: 9/14/2011
      • Status: offline
      Re:Last domain logon for specific user Thursday, September 15, 2011 9:55 PM (permalink)
      0
      59cobalt

      Why would you want to do that? With Windows Server 2003 a new attribute lastLogonTimestamp was introduced that is replicated across domain controllers. And since Windows 2000 reached EoL in July 2010 you really don't want to use earlier versions anyway.

      I thought of that, but unfortunately the lastLogonTimeStamp only updates when the user logs on and the old value is more than 14 days old.

      59cobalt
      Reading sAMAccountName is utterly pointless when you already used the sAMAccountName as a filter in your query. You'd be wasting resources on obtaining information that you already have.

      Ha! good point, thanks for pointing that out
       
      #3
        wenbibi

        • Total Posts : 11
        • Scores: 0
        • Reward points : 0
        • Joined: 12/18/2011
        • Status: offline
        Re:Last domain logon for specific user Sunday, December 18, 2011 4:36 PM (permalink)
        0

        Hi,I’m xxx. I'm 13 years old and I study in xxx Middle School. Bike Trials  My school is ...Every morning I get up at seven and have breakfast. And then I go to school at half past seven. Bike Trial Seller  Lessons begin at eight o’clock. We have four lessons in the morning and Chinese is my favourite lesson. Bike Store We usually have 10 minute's break between two lessons and at about 12 o'clock we finish our morning lessons. I have lunch at school at twelve thirty.I like school lunch and I always have rice with meat and vegetables. Bike Shop
         
        #4

          Online Bookmarks Sharing: Share/Bookmark

          Jump to:

          Current active users

          There are 0 members and 1 guests.

          Icon Legend and Permission

          • New Messages
          • No New Messages
          • Hot Topic w/ New Messages
          • Hot Topic w/o New Messages
          • Locked w/ New Messages
          • Locked w/o New Messages
          • Read Message
          • Post New Thread
          • Reply to message
          • Post New Poll
          • Submit Vote
          • Post reward post
          • Delete my own posts
          • Delete my own threads
          • Rate post

          2000-2012 ASPPlayground.NET Forum Version 3.9