Domain user Last-logon-Timestamp not get updated from DC and ADC.

Posted on 2009-12-27
Last Modified: 2012-05-08
Last-logon-Timestamp not get updated from DC and ADC.
need command to sync the same.
Question by:mash1978

    Author Comment


    Time on DC and ADC are same no difference.

    i want to disable unused accounts and if users Last-logon-Timestamp are different in DC and ADC
    in active directory user account information . if script run on Dc and new user last logged on ADC then it's account get disable.
    LVL 76

    Expert Comment

    run dcdiag and netdiag to make sure there are no sync/replication problems.
    Check the event logs on both for clues as well.
    Alternatively, you can setup a GPO with a login/logout script that applies to all user that records their login/logout events.

    A similar script can be used for the logout script.

    You could use a VBS script and do the same thing inserting the data into an SQL database.
    @echo off
    echo %DATE% %TIME% %USERNAME% Loggged in %COMPUTERNAME% %SESSIONNAME% >> \\someshareserver\sharename\recordfile.txt

    Open in new window

    LVL 31

    Expert Comment

    by:Henrik Johansson
    This is expected as the last logon attribute is a information about when user last authenticated with the specific DC, and this information isn't replicated between the DCs.
    If you want the actual last logon timestamp when having multiple DCs, you nead to check each DC as the information will not be replicated.
    Instead of connecting to each DC, it's preferably done with a script.

    So, your thaught about disable the user on a criteria with different logon timestamp on different DC wouldn't be a good idea.

    As you want to find inactive users, use dsquery (MS standard tool in adminpak.msi) or adfind (, you can query for inactive users

    To query domain for all users that has been inactive for 5 weeks by using dsquery:
    dsquery user -inactive 5 -limit 0

    If you want to automate the disabling, you can pipe the result to dsmod
    dsquery user -inactive 5 -limit 0 | dsmod user -inactive yes

    Author Comment

    To query domain for all users that has been inactive for 5 weeks by using dsquery:
    dsquery user -inactive 5 -limit 0

    If you want to automate the disabling, you can pipe the result to dsmod
    dsquery user -inactive 5 -limit 0 | dsmod user -inactive yes

    Above commands will search for users last logon attribute on both DC and ADC or only any of one.
    LVL 15

    Accepted Solution

    Here you go, this script will disable accounts that have not logged on for more than 60 days.  Just search for "60" to change the number of idle days if you need to alter that time frame.
    ' NAME: Disable60DayIdle.vbs
    ' AUTHOR: Mark D. MacLachlan , The Spider's Parlor
    ' URL:
    ' DATE  : 11/18/2004
    ' COMMENT: Determines when each user in the domain last logged on
    '          Disables accounts inactive for 60 days or more
    '          Thanks to Richard Mueller for sample code to query DCs.
    ' Because the lastLogon attribute is not replicated, every Domain
    ' Controller in the domain must be queried to find the latest lastLogon
    ' date for each user. The lastest date found is kept in a dictionary
    ' object. The program first uses ADO to search the domain for all Domain
    ' Controllers. The AdsPath of each Domain Controller is saved in an
    ' array. Then, for each Domain Controller, ADO is used to search the
    ' copy of Active Directory on that Domain Controller for all user
    ' objects and return the lastLogon attribute. The lastLogon attribute is
    ' a 64-bit number representing the number of 100 nanosecond intervals
    ' since 12:00 am January 1, 1601. This value is converted to a date. The
    ' last logon date is in UTC (Coordinated Univeral Time). It must be
    ' adjusted by the Time Zone bias in the machine registry to convert to
    ' local time.
    Dim objRootDSE, strConfig, objConnection, objCommand, strQuery
    Dim objRecordSet, objDC
    Dim strDNSDomain, objShell, lngBiasKey, lngBias, k, arrstrDCs()
    Dim strDN, dtmDate, objDate, lngDate, objList, strUser, IdleAge
    Dim strBase, strFilter, strAttributes, lngHigh, lngLow
    Dim outfile, Report, fso, ts, ForWriting
    IdleAge = "60"
    ' Use a dictionary object to track latest lastLogon for each user.
    Set objList = CreateObject("Scripting.Dictionary")
    objList.CompareMode = vbTextCompare
    ' Obtain local Time Zone bias from machine 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)
    End If
    ' Determine configuration context and DNS domain from RootDSE object.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strConfig = objRootDSE.Get("configurationNamingContext")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    ' Use ADO to search Active Directory for ObjectClass nTDSDSA.
    ' This will identify all Domain Controllers.
    Set objCommand = CreateObject("ADODB.Command")
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    objCommand.ActiveConnection = objConnection
    strBase = "<LDAP://" & strConfig & ">"
    strFilter = "(objectClass=nTDSDSA)"
    strAttributes = "AdsPath"
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    objCommand.CommandText = strQuery
    objCommand.Properties("Page Size") = 100
    objCommand.Properties("Timeout") = 60
    objCommand.Properties("Cache Results") = False
    Set objRecordSet = objCommand.Execute
    ' Enumerate parent objects of class nTDSDSA. Save Domain Controller
    ' AdsPaths in dynamic array arrstrDCs.
    k = 0
    Do Until objRecordSet.EOF
      Set objDC = _
      ReDim Preserve arrstrDCs(k)
      arrstrDCs(k) = objDC.DNSHostName
      k = k + 1
    ' Retrieve lastLogon attribute for each user on each Domain Controller.
    For k = 0 To Ubound(arrstrDCs)
      strBase = "<LDAP://" & arrstrDCs(k) & "/" & strDNSDomain & ">"
      strFilter = "(&(objectCategory=person)(objectClass=user))"
      strAttributes = "distinguishedName,lastLogon"
      strQuery = strBase & ";" & strFilter & ";" & strAttributes _
        & ";subtree"
      objCommand.CommandText = strQuery
      On Error Resume Next
      Set objRecordSet = objCommand.Execute
      If Err.Number <> 0 Then
        On Error GoTo 0
        Wscript.Echo "Domain Controller not available: " & arrstrDCs(k)
        On Error GoTo 0
        Do Until objRecordSet.EOF
          strDN = objRecordSet.Fields("distinguishedName")
          lngDate = objRecordSet.Fields("lastLogon")
          On Error Resume Next
          Set objDate = lngDate
          If Err.Number <> 0 Then
            On Error GoTo 0
            dtmDate = #1/1/1601#
            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/1601#
              dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
                + lngLow)/600000000 - lngBias)/1440
            End If
          End If
          If objList.Exists(strDN) Then
            If dtmDate > objList(strDN) Then
              objList(strDN) = dtmDate
            End If
            objList.Add strDN, dtmDate
          End If
      End If
    For Each strUser In objList
    	lnameArray = split(strUser,",")
    	nameLength = Len(lnameArray(0)) - 3
    	lname = Right(lnameArray(0),nameLength)
    	Select Case LCase(lname)
    	      'Add additional accounts to ignore here
    		  Case "guest","krbtgt","administrator"
    		  		'Do Nothing
    		  Case Else
    		    If DateDiff("d",objList(strUser), Now()) >= CInt(IdleAge) Then
    		      ' Now Disable the account, remove group memberships and move the account
    			End If
    		End Select
    ' Clean up.
    Set objRootDSE = Nothing
    Set objConnection = Nothing
    Set objCommand = Nothing
    Set objRecordSet = Nothing
    Set objDC = Nothing
    Set objDate = Nothing
    Set objList = Nothing
    Set objShell = Nothing
    Function DisableUser(userDN)
    	On Error Resume Next
    	Dim oRootDSE, oConnection, objCommand, ldstring, oRecordset, disUser, newDescription
    	Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D
    	Set oRootDSE = GetObject("LDAP://rootDSE")
    	DisOUstr = "LDAP://OU=Disabled Users,OU=Users,OU=Parsippany," & oRootDSE.get("defaultNamingContext")
    	Set objOU = GetObject(DisOUstr)
    	Set objUser = GetObject("LDAP://" & userDN)
    	newDescription = "TERM - DEL on " & Date()+30
    	'update the user description
    	objUser.Put "description", newDescription
    	'Now remove group memberships
    	arrMemberOf = objUser.GetEx("memberOf")
    	If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
    		    'This account is not a member of any security groups.
    			For Each Group in arrMemberOf
    				Set objGroup = GetObject("LDAP://" & Group) 
    			    objGroup.PutEx ADS_PROPERTY_DELETE, _
    			        "member", Array(userDN)
    	End If
    	'Hide from the GAL
    	objUser.Put "msExchHideFromAddressLists", True
    	'Now disable the account
    	intUAC = objUser.Get("userAccountControl")
    	objUser.Put "userAccountControl", intUAC OR ADS_UF_ACCOUNTDISABLE
    	'Move the account
    	objOU.MoveHere objUser.ADsPath, objUser.Name
    End Function

    Open in new window


    Author Comment

    Good , Thanks

    Featured Post

    Gigs: Get Your Project Delivered by an Expert

    Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

    Join & Write a Comment

    I guess it is not common knowledge to most Wintel engineers/administrators: If you have an SNMP-based monitoring system in your environment (and it's common to have SNMP or Syslog) it's reasonably easy to enable monitoring of the Windows Event logs,…
    Recently, I had the need to build a standalone system to run a point-of-sale system. I’m running this on a low-voltage Atom processor, so I wanted a light-weight operating system, but still needed Windows. I chose to use Microsoft Windows Server 200…
    Internet Business Fax to Email Made Easy - With eFax Corporate (, you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
    This video discusses moving either the default database or any database to a new volume.

    734 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    21 Experts available now in Live!

    Get 1:1 Help Now