Lastlogon: Many DCs showing Identical Timestamp

  • Thread starter Thread starter chessexpert
  • Start date Start date
C

chessexpert

I am using the "Additional Account Info" tab on the AD Users and Computers
GUI (acctinfo.dll) to compare Last Logon timestamp to the values that I get
using Vbscript's Get method, and GetEx method (e.g. set objLogon =
ousr.Get("lastLogon")). I am specifying a specific DC to query in the LDAP
path in the Vbscript. I noticed that many user accounts have the identical
timestamp on many DCs in the "Additional Account Info" tab on the DCs. How
can this be? Also, the results will always match the output from the Get
method, or the Getex method, but not both. There seems to be no pattern.
 
chessexpert said:
I am using the "Additional Account Info" tab on the AD Users and Computers
GUI (acctinfo.dll) to compare Last Logon timestamp to the values that I
get
using Vbscript's Get method, and GetEx method (e.g. set objLogon =
ousr.Get("lastLogon")). I am specifying a specific DC to query in the LDAP
path in the Vbscript. I noticed that many user accounts have the identical
timestamp on many DCs in the "Additional Account Info" tab on the DCs. How
can this be? Also, the results will always match the output from the Get
method, or the Getex method, but not both. There seems to be no pattern.

The lastLogon and lastLogonTimeStamp attributes are not the same. The
lastLogon attribute is updated every time the user logs on, but only on the
DC that authenticated the user. The value is not replicated, so a different
value for the user is maintained on every DC. To get an accurate value you
must query every DC in the domain for the largest (latest) value.

The lastLogonTimeStamp attribute was added in Windows Server 2003. It is
only updated if the old value is more than 14 days in the past (by default).
However it is replicated, so the same value for the user (after replication)
is found on all DC's.
 
Yes, but that still does not explain why I have multiple DCs showing the
exact same date/time in the GUI for a specific user. Since this does not get
replicated, how is it that so many (but not all) DCs have the exact Last
Logon date/time for a particular user (i.e. how can that user get
authenticated on many DCs at the same time?)Perhaps one DC was used as a
template during a restore or build process, and that captured the Last Logon
info on all DCs that copied the AD database? And why is it that the GUI does
not always match the AD query? It is as if the AD query is not going to the
DC that I specify in the LDAP path, but perhaps rather whichever responds
first? Basically I need a way to determine tha actual last long date on each
DC. But sometime the Gui matches the VBScript Get method, and other times it
matches the GetEx method.
 
chessexpert said:
Yes, but that still does not explain why I have multiple DCs showing the
exact same date/time in the GUI for a specific user. Since this does not
get
replicated, how is it that so many (but not all) DCs have the exact Last
Logon date/time for a particular user (i.e. how can that user get
authenticated on many DCs at the same time?)Perhaps one DC was used as a
template during a restore or build process, and that captured the Last
Logon
info on all DCs that copied the AD database? And why is it that the GUI
does
not always match the AD query? It is as if the AD query is not going to
the
DC that I specify in the LDAP path, but perhaps rather whichever responds
first? Basically I need a way to determine tha actual last long date on
each
DC. But sometime the Gui matches the VBScript Get method, and other times
it
matches the GetEx method.

If you are retrieving the value of lastLogon for a user from several DC's,
you are right that they should not be the same (except for the value 0,
which means never). Values of lastLogonTimeStamp should be the same. If you
specify the DNS name of the DC in the binding string, only that DC should
respond. To specify a particular DC I use code similar to:

Set objUser = GetObject("LDAP://MyServer.MyDomain.com/cn=Jim
Smith,ou=West,dc=MyDomain,dc=com")

If the DC is not available an error should be raised. I've never heard of
using the GetEx method. I thought it was only for multi-valued attributes. I
use code simiilar to (using the IADsLargeInteger interface):

Set objDate = objUser.Get("lastLogon")
Wscript.Echo objDate.HighPart & ", " & objDate.LowPart

However I experimented with GetEx and found it retrieves lastLogon as a
Variant() array with one element, which is an object, although you cannot
use the Set keyword. I used this code:

objDate = objUser.GetEx("lastLogon")
Wscript.Echo objDate(0).HighPart & ", " & objDate(0).LowPart

This gave me the exact same result for both high and low 32-bit parts of the
64-bit value. Note that the standard formula for calculating the 64-bit
value (in VB and VBScript) using the IADsLargeInteger interface is:
=========
Set objDate = objUser.Get("lastLogon")
lngHigh = objDate.HighPart
lngLow = objDate.LowPart

lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440
dtmDate = CDate(lngDate)
=========
However there is a problem in the IADsLargeInteger interface, which only
reveals itself half the time and gives answers only off by 7 minutes 9.5
seconds. The fix is as follows:
=========
Set objDate = objUser.Get("lastLogon")
lngHigh = objDate.HighPart
lngLow = objDate.LowPart

' Account for error in IADsLargeInteger property methods.
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If

lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440

dtmDate = CDate(lngDate)
=======
Also, the resulting date is in UTC, so you must correct by the time zone
bias to convert to local time. I mention this in case this accounts for
differences between what you calculate in code and what you see in something
like ADSI Edit or the GUI. Since LowPart runs from -2^31 to 2^31-1, the
correction is needed half the time. Incrementing the HighPart by 1 is
equivalent to 7 minutes 9.5 seconds. I'm assuming the same correction must
be made if you use the GetEx method, but I would have to experiment more.
 
Back
Top