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

System.InvalidCastException: Cast from type '_ComObject' to type 'String' is not valid

Hi,

I'm using a function to retrieve properties from a DirectoryServices object.

Unfortunately, the function fails whenever I trry to assign the object properties "accountExpires" to a string value with the error: System.InvalidCastException: Cast from type '_ComObject' to type 'String' is not valid.

The function I am using is as follows:

Public Function GetObjectProperties(ByVal DN As String, ByVal PropertyName As String) As String

        Dim strOutput As String

        Dim DE As New DirectoryEntry
        DE.Path = "LDAP://" & ServerName & "/" & DN
        DE.Username = AdminUsername
        DE.Password = AdminPassword

        Try

            DE.RefreshCache()
            If DE.SchemaClassName = "user" Then

                strOutput = CStr(DE.Properties(PropertyName).Value)

            End If

        Catch ex As Exception

            'TODO: Raise an error
            strOutput = "Exception! Input DN was = " & DN & "<BR>The error was: " & ex.ToString


        End Try

        Return strOutput
        DE.Dispose()

    End Function

I know this function works, as it WILL retreive other properties, such as 'CN'. But it dies on trying to retrieve the expiration date.

Cheers
0
OnError_Fix
Asked:
OnError_Fix
  • 5
  • 4
1 Solution
 
RacinRanCommented:
accountExpires is a datetime data type.  Try to cast it as a date.

Racin
0
 
OnError_FixAuthor Commented:
Nope, that didn't work either:
System.InvalidCastException: Cast from type '_ComObject' to type 'Date' is not valid.

0
 
OnError_FixAuthor Commented:
Note: here's the latest function:

E.Path = "LDAP://" & ServerName & "/" & DN
        DE.Username = AdminUsername
        DE.Password = AdminPassword

        Try

            DE.RefreshCache()
            If DE.SchemaClassName = "user" Then

                Return DE.Properties(PropertyName).Value

            End If

        Catch ex As Exception

            'TODO: Raise an error
            Return "Exception! Input DN was = " & DN & "<BR>The error was: " & ex.ToString


        End Try
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ihenryCommented:
Hello again,

When you get the accountExpires attribute value from AD direct binding, it returns as COM interface IADsLargeInteger which is not very "friendly" to any CLR data type. Therefore you can't cast it directly to String or DateTime. One article on IADsLargeInteger interface.

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

In VB.NET (or C#) you have to use COM interop or reflection. One way is to get the HighPart and LowPart values of the interface and combine them into a long integer.

Dim int64Val as IADsLargeInteger = DirectCast( thePropertyValue, IADsLargeInteger )
Dim longInteger As Int64 = Convert.ToInt64( int64Val.HighPart ) * 4294967296 + Convert.ToInt64( int64Val.LowPart )

Finally to convert it to DateTime value,

Dim accountExpires  As DateTime = DateTime.FromFileTime( longInteger )
0
 
OnError_FixAuthor Commented:
Hi iHenry,

As always I appreciate your help. The problem this time was that I got an error, "The input string was in an invalid format" when executing your code. It didn't like the following line: Dim longInteger As Int64 = Convert.ToInt64( int64Val.HighPart ) * 4294967296 + Convert.ToInt64( int64Val.LowPart ) where it reported an 'overflow'.

I tried Microsoft's code:

Dim ExpiresOn As String = CStr(Hex(int64val.HighPart)) + CStr(Hex(int64val.LowPart))

Which produced a string of the following:

7FFFFFFFFFFFFFFF

No matter which user it was retrieving the property for. So I'm confused!

Any ideas?
0
 
ihenryCommented:

I have the similar code in C#, I think I screwed up VB.NET type conversion. Try get rid the conversion and see how it goes.

Dim longInteger As Int64 = int64Val.HighPart * 4294967296 + int64Val.LowPart
0
 
ihenryCommented:

Hello OnError_Fix,

Hows the problem, solved?
0
 
OnError_FixAuthor Commented:
Hi iHenry.... sorry for the delay in replying (work!!).

No, unfortunately the problem is still the same. Any ideas on how to proceed now?
0
 
ihenryCommented:

I'm not very sure why it doesn't work for you. I guess you need more information.

excerpt from active directory platform sdk
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/adschema/adschema/a_accountexpires.asp
-----------------------------
The accountExpires attribute specifies when an account expires. This value is stored as a large integer that represents the number of 100-nanosecond intervals since January 1, 1601 (UTC). A value of TIMEQ_FOREVER (defined in Lmaccess.h) indicates that an account never expires.

Note: TIMEQ_FOREVER  here is equal to hex 0xFFFFFFFF or decimal -1

So here is the deal,

When the user account is set to have an expiry date you should be able to retrieve the value with this code (it tested and works)

Dim largeInteger As IADsLargeInteger = DirectCast(user.Properties("accountExpires").Value, IADsLargeInteger)
Dim int64Val As Int64 = int64Val.HighPart * 4294967296 + int64Val.LowPart
Dim expiryDate = DateTime.FromFileTime(int64Val)

However, when the user account is set to be never expire int64Val.HighPart and int64Val.LowPart have 2147483647 and -1, respectively.
0
 
OnError_FixAuthor Commented:
Nice one, iHenry....

Apologies for the delay in getting these to you. Thanks again!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

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