I have a program with a long running Active Directory query. I wanted to take advantage of VB.NET's Async technology, but when I converted my function to Async, I started getting an InvalidCastException. When I switch back, the error goes away. Why is Async causing an InvalidCastException for my COM object?
Exception Message:
Unable to cast COM object of type 'System.__ComObject' to interface type 'IDirectorySearch'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{109BA8EC-92F0-11D0-A790-00C04FD8D5A8}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
This must be happening somewhere within the core library, because I don't have any references to IDirectorySearch in my code. Indeed, the stack trace is not very illuminating:
Here's where the exception is thrown (according to the debugger):
Private Overloads Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Here's the actual code. I've created two versions to demonstrate the code before (FindAll1) and after (FindAll2) async:
Private Async Sub FindAllButton_Click(sender As Object, e As RoutedEventArgs) Handles FindAllButton.Click
'Me.Entries = Await FindAll1(Me.FilterText) ' Works
Me.Entries = Await FindAll2(Me.FilterText) ' Doesn't Work
End Sub
Private Async Function FindAll1(filterText As String) As Task(Of IEnumerable(Of DirectoryEntryWrapper))
Dim l_searcher As New DirectorySearcher()
l_searcher.SizeLimit = Me.QuerySizeLimit
l_searcher.Filter = filterText
Me.IsLoading = True
Dim l_results =
From result In l_searcher.FindAll().Cast(Of SearchResult)()
Select entry =
New DirectoryEntryWrapper(result.GetDirectoryEntry(), AddressOf DirectoryEntryWrapperEventHandler)
Order By entry.Name
Me.IsLoading = False
Return l_results
End Function
Private Async Function FindAll2(filterText As String) As Task(Of IEnumerable(Of DirectoryEntryWrapper))
Dim l_searcher As New DirectorySearcher()
l_searcher.SizeLimit = Me.QuerySizeLimit
l_searcher.Filter = filterText
Me.IsLoading = True
Dim l_results =
Await Task.Run(
Function() _
From result In l_searcher.FindAll().Cast(Of SearchResult)()
Select entry =
New DirectoryEntryWrapper(result.GetDirectoryEntry(), AddressOf DirectoryEntryWrapperEventHandler)
Order By entry.Name
)
Me.IsLoading = False
Return l_results
End Function