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.
LVL 1
HatchITAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.