• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4463
  • Last Modified:

lastLogon format from AD (via LDAP)

Can someone please tell me what I'm doing wrong here?  I've been trying to get this (seemingly) simple thing to work, but it seems to be beyond me.  I'm trying to write a VB.NET program to get the last logon time for a user.  The form has a combo box that is loaded with sites at startup.  When a site is selected, a list box gets all the users in that site.  When the username is double-clicked, it calls the following code:

  Sub CheckLastLogon(ByVal strSite As String, ByVal strUser As String)
    Dim strUserDN As String = "LDAP://CN=" & strUser & ",OU=Users,OU=" & strSite & strDomain
    Dim deUser As New DirectoryEntry(strUserDN)
    Dim pvcLast As PropertyValueCollection = deUser.Properties("lastLogon")
    '??????
  End Sub

The problem is that I can't for the life of me figure out what to do with the "pvcLast" variable once I've retrieved it.  For now, I'd like to just get it to display in a MsgBox so I know that I'm retrieving it correctly; I can do more with it later, once I've gotten it in the first place.  Most things I try to do to it either give me a "Type Mismatch" error or, even more helpful (to me, at least) "System.ArgumentException - Argument 'Prompt' cannot be converted to type 'String'." or some such.  The VBScript version of doing this seems so easy, why should the VB.NET version be so difficult?  Grr.

PS: Yes, I realize that later I'm going to have to modify it so that it'll check all domain controllers.  Right now I just want to see that I can get the lastLogon value, and successfully convert it into a valid date/time.
0
HatchIT
Asked:
HatchIT
  • 2
  • 2
1 Solution
 
ihenryCommented:
Hello HatchIT

When you get the lastLogon attribute value via Active Directory direct binding, it returns COM interface IADsLargeInteger which is not part of native CLR data types. One reading on IADsLargeInteger interface.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adsi/adsi/iadslargeinteger.asp

In VB.NET, you have to use import ADSI COM dll and get the property value from HighPart and LowPart value of the IADsLargeInteger nterface and combine them into a long integer.

Sample code:

Dim int64Val As IADsLargeInteger = DirectCast(user.Properties("lastLogon").Value, IADsLargeInteger)
Dim longInteger As Int64 = int64Val.HighPart * 4294967296 + int64Val.LowPart
' display last login date in OS system file timestamp
Console.WriteLine(DateTime.FromFileTime(longInteger))


0
 
ihenryCommented:
I understand you need more than ADSI data type conversion. Try the following code

        Dim user As DirectoryEntry

        Try

            user = New DirectoryEntry
            user.Path = theLdapPath

          ' use the next 3 lines when your current login account doesn't have enough permission
            user.Username = "theDomainName\theUserName"
            user.Password = "thePassword"
            user.AuthenticationType = AuthenticationTypes.None

            user.RefreshCache()

            Dim int64Val As IADsLargeInteger = DirectCast(user.Properties("lastLogon").Value, IADsLargeInteger)
            Dim longInteger As Int64 = int64Val.HighPart * 4294967296 + int64Val.LowPart
            Console.WriteLine(DateTime.FromFileTime(longInteger))

        Catch ex As COMException
            Throw
        Finally
            If Not IsNothing(user) Then
                user.Close()
                user.Dispose()
            End If
        End Try
    End Sub
0
 
HatchITAuthor Commented:
Heh, two things that nothing I'd been able to find gave me the two peices of info I needed:

1) Add reference to "Active DS Type Library" COM object.  Even that MS article you sent me said to use activeds.dll, but in the COM reference list, "Active DS Type Library" uses activeds.tlb
2) Use the IADsLargeInteger type to handle the data.

Below is what's working for me now:

0
 
HatchITAuthor Commented:
Oops, meant to click in the comment box, missed and clicked "Submit"  :-P  Continued from last post...

  Sub CheckLastLogon(ByVal strSite As String, ByVal strUser As String)
    Dim strUserDN As String = "LDAP://CN=" & strUser & ",OU=Users,OU=" & strSite & strDomain
    Dim deUser As New DirectoryEntry(strUserDN)
    Dim intLast As IADsLargeInteger = DirectCast(deUser.Properties("lastLogon").Value, IADsLargeInteger)
    Dim lngLast As Long = intLast.HighPart * 4294967296 + intLast.LowPart
    MsgBox(DateTime.FromFileTime(lngLast))
    deUser.Close()
    deUser.Dispose()
  End Sub

Thanks for that, jhenry.  :-)
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now