Answered LastLogonTimeStamp

  • Friday, January 11, 2013 5:03 PM
     
     

    Found the following script on the web.  It works great if you want to get the LastLogonTimeStamp from every object in the OU.  What i would like to be able to do is specifiy a "username", search AD, and get the lastlogontimestamp for that user.  We run Win2K3 and Win2k8 and would only query one DC.

    Can anyone help mod this script to allow for the entry of a single username/logoname/sAMAccountName and get the LastLogonTimeStamp attribute?

    Option Explicit
    Dim objOU, objUser, objRootDSE, objLastLogon
    Dim strContainer, strDNSDomain
    Dim intLastLogonTime, intGuyTime

    strContainer = "ou=AMER,ou=Regions,"

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("DefaultNamingContext")

    strContainer = strContainer & strDNSDomain
    Set objOU = GetObject("LDAP://" & strContainer)


    For Each objUser In objOU
        Set objLastLogon = objUser.Get("lastLogon")
        intLastLogonTime = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
        intLastLogonTime = intLastLogonTime / (60 * 10000000)
        intLastLogonTime = intLastLogonTime / 1440

        MsgBox objUser.FirstName & " " & objUser.LastName & " 's last logon time: " & intLastLogonTime + #1/1/1601#
    Next

    Thanks,

    Dave Casson


    Dave

All Replies

  • Friday, January 11, 2013 5:08 PM
    Moderator
     
     Proposed Has Code

    Here's the short version of how to do it using the get-aduser AD cmdlet:


    PS C:\> $timeStamp = (get-aduser username).lastLogonTimeStamp
    PS C:\> [DateTime]::FromFileTime($timeStamp)
    

    Bill

  • Friday, January 11, 2013 5:13 PM
     
     

    Seems to give me the same time stamp for each user I try even though I know they should be different.

    Dave


    Dave

  • Friday, January 11, 2013 5:15 PM
    Moderator
     
     Answered Has Code

    Hi,

    You have to repeat both commands for each user you want to check (change username from the first command every time). Here's a single-command version of the above two lines:


    PS C:\> [DateTime]::FromFileTime((get-aduser username -properties lastLogonTimestamp).lastLogonTimestamp)

    I split it into two separate commands to make it easier to see what's going on.

    Bill

  • Friday, January 11, 2013 5:54 PM
     
     

    Seems to be working now thanks.  Would still like to get the VB script above working like that. But, this will work for now.

    Thanks again,

    Dave


    Dave

  • Friday, January 11, 2013 5:57 PM
    Moderator
     
     

    Hi,

    The problem with the VBScript version is that VBScript does not support 64-bit integers. The VBScript code you posted, above, attempts to "shoehorn" a 64-bit value into a 32-bit variable, which can result in a lack of resolution for the number. PowerShell natively supports 64-bit integers, so the results will be more exact.

    Bill

  • Friday, January 11, 2013 6:01 PM
     
     

    Cool thanks.

    Dave


    Dave

  • Friday, January 11, 2013 6:39 PM
    Moderator
     
      Has Code

    VBScript can use the IADsLargeInteger interface to convert the 64-bit Integer8 value into a date in the local time zone. For example:

    Option Explicit

    Dim objShell, lngBiasKey, k, lngBias, objUser, objLast, lngLast, dtmLast

    ' Obtain local Time Zone bias from machine registry.
    ' This bias changes with Daylight Savings Time.
    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

    ' Bind to the user object in AD
    Set objUser = GetObject("LDAP://cn=Jim Smith,ou=West,dc=MyDomain,dc=com")

    ' Retrieve lastLogonTimeStamp using IADsLargeInteger interface.
    Set objLast = objUser.lastLogonTimeStamp

    ' Convert into 64-bit integer.
    lngLast = objLast.HighPart * (2^32) + objLast.LowPart

    ' Convert into date in the local time zone.
    dtmLast = Integer8Date(lngLast, lngBias)
    Wscript.Echo "Last logon date: " & dtmlast

    Function Integer8Date(ByVal lngValue, ByVal lngBias)
        ' Function to convert Integer8 (64-bit) value to a date, adjusted for
        ' local time zone bias.
        Dim lngDate
        lngDate = #1/1/1601# + (lngValue/600000000 - lngBias)/1440
        ' Trap error if lngDate is ridiculously huge.
        On Error Resume Next
        Integer8Date = CDate(lngDate)
        If (Err.Number <> 0) Then
            On Error GoTo 0
            Integer8Date = #1/1/1601#
        End If
        On Error GoTo 0
    End Function

    -----

    If the user has never logged on, the function returns the AD "zero" date, which is Jan. 1, 1601.


    Richard Mueller - MVP Directory Services

  • Friday, January 11, 2013 8:22 PM
    Moderator
     
     

    But even though the original value (Integer8) is 64 bits, you can't convert to a 32-bit value without losing precision.

    Bill

  • Friday, January 11, 2013 10:52 PM
    Moderator
     
     

    You are correct Bill, that VBScript cannot exactly represent 64-bit integers. But VBscript can handle 15 decimal digits exactly. It can represent integers up to 2^53 exactly. Integer8 values can be up to 19 digits, although current dates are now 1.3 x 10^17, which is 18 digits. This means the last several digits will be zeros. Still, that is accurate to much better than a second.


    Richard Mueller - MVP Directory Services