2014-09-24 51 views
0

我有一個類,它在Active Directory中搜索所有OU,然後搜索其中的所有計算機對象。它正在完美工作......然後我決定利用一些線程來允許OU搜索和計算機對象搜索同時運行。現在突然間,計算機搜索器正在返回0結果...(沒有錯誤,只是根本沒有結果)VB.Net DirectorySearcher更改爲使用多個線程後返回0結果

我也添加了一個額外的屬性來加載(objectGUID),但我試過刪除它和它沒有解決問題。我看不到我已經做了什麼來打破它。這可能是愚蠢的把我凝視在臉上,但我無法找到它。我希望一雙新鮮的眼睛能夠發現我的錯誤。

在破損的代碼Public Sub FindComputers(...)是我遇到問題的地方。 在工作代碼中是Private Function FindComputers(...)。我改變了它,因爲它現在在一個單獨的課堂上。

編輯: 我在FindComputers子上設置了一個斷點並逐步完成了它。執行queryResults = searcher.FindAll()行後,queryResults count始終爲0.循環中的事件永遠不會被觸發。

在此先感謝。

原來這裏是工作代碼:

Public Class ADSearcher 

'Removed properties and events etc 

Public Sub StartSearch() 

#If Not Debug Then 
    Try 
#End If 

    Dim rootEntry As New DirectoryEntry(RootPath) 
    Dim rootNode As New TreeNode(rootEntry.Name) 
    rootNode.Name = rootEntry.Path 

    If Not IntegratedAuthentication Then 
     rootEntry.Username = UserID 
     rootEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(rootEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = FilterString 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 

     FindComputers(result) 'Search the current OU for computer objects 

     Dim childNode As New TreeNode(CStr(result.Properties("name")(0))) 
     childNode.Name = result.Path 
     rootNode.Nodes.Add(SearchSub(result, childNode)) 

     ouResultCount += 1 
     RaiseEvent ResultFound(ouResultCount, pcResultCount) 
    Next 

    RaiseEvent SearchCompleted(rootNode) 
    ouResultCount = 0 'Reset the result count 
    pcResultCount = 0 'Reset the computer result count 


#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Sub 

Private Function SearchSub(ByVal parent As SearchResult, ByVal node As TreeNode) 
#If Not Debug Then 
    Try 
#End If 
    Dim subEntry As New DirectoryEntry(parent.Path) 

    If Not IntegratedAuthentication Then 
     subEntry.Username = UserID 
     subEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(subEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = FilterString 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 
     FindComputers(result) 'Search for computer objects in the current OU 

     Dim childNode As New TreeNode(CStr(result.Properties("name")(0))) 
     childNode.Name = result.Path 
     SearchSub(result, childNode) 
     node.Nodes.Add(childNode) 
     ouResultCount += 1 
     RaiseEvent ResultFound(ouResultCount, pcResultCount) 
    Next 

    Return node 

#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Function 

Private Function FindComputers(ByVal parent As SearchResult) 
#If Not Debug Then 
    Try 
#End If 
    Dim subEntry As New DirectoryEntry(parent.Path) 

    If Not IntegratedAuthentication Then 
     subEntry.Username = UserID 
     subEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(subEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = "(objectCategory=computer)" 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 
     pcResultCount += 1 

     Dim dNSHostName As String 
     If result.Properties.Contains("dNSHostName") Then 
      dNSHostName = result.Properties("dNSHostName")(0) 
     Else 
      dNSHostName = result.Properties("name")(0) 'If the computer object has a value in dNSHostName (FQDN) store it else store the basic name 
     End If 

     RaiseEvent ComputerFound(result.Properties("name")(0), dNSHostName, result.Path) 
     RaiseEvent ResultFound(ouResultCount, pcResultCount) 
    Next 

    Return 1 

#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Function 

End Class 

這是當前斷碼:

Public Class ADSearcher 

'Removed properties and events etc 

<MTAThread()> 
Public Sub StartSearch() 

#If Not Debug Then 
    Try 
#End If 

    Dim rootEntry As New DirectoryEntry(RootPath) 
    Dim rootNode As New TreeNode(rootEntry.Name) 
    rootNode.Name = rootEntry.Path 

    If Not IntegratedAuthentication Then 
     rootEntry.Username = UserID 
     rootEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(rootEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = FilterString 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 

     Dim freeThread As Integer = WaitHandle.WaitAny(compSearchThreads) 

     Dim threadParams As Object 
     threadParams = New Object() {result, freeThread} 'Create an object to pass the parameters 

     compSearchInstances(freeThread) = New ComputerSearcher(compSearchThreads(freeThread)) 

     With compSearchInstances(freeThread) 
      .FilterString = "(objectCategory=computer)" 
      If Not IntegratedAuthentication Then 
       .UserID = UserID 
       .Password = Password 
      End If 
      .PageSize = 5 
      .PropertiesToLoad = New String() {"cn", "name", "distinguishedName", "dNSHostName", "objectCategory", "objectGUID"} 
     End With 

     ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf compSearchInstances(freeThread).FindComputers), threadParams) 
     'FindComputers(result) 'Search the current OU for computer objects 

     Dim childNode As New TreeNode(CStr(result.Properties("name")(0))) 
     childNode.Name = result.Path 
     childNode.Tag = result.Properties("objectGUID")(0) 
     rootNode.Nodes.Add(SearchSub(result, childNode)) 

     ouResultCount += 1 
     RaiseEvent OUResultFound(ouResultCount) ', pcResultCount) 
    Next 

    WaitHandle.WaitAll(compSearchThreads) 
    RaiseEvent SearchCompleted(rootNode) 
    ouResultCount = 0 'Reset the result count 
    'pcResultCount = 0 'Reset the computer result count 


#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Sub 

Private Function SearchSub(ByVal parent As SearchResult, ByVal node As TreeNode) 
#If Not Debug Then 
    Try 
#End If 
    Dim subEntry As New DirectoryEntry(parent.Path) 

    If Not IntegratedAuthentication Then 
     subEntry.Username = UserID 
     subEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(subEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = FilterString 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 

     Dim freeThread As Integer = WaitHandle.WaitAny(compSearchThreads) 

     Dim threadParams As Object 
     threadParams = New Object() {result, freeThread} 'Create an object to pass the parameters 

     compSearchInstances(freeThread) = New ComputerSearcher(compSearchThreads(freeThread)) 

     With compSearchInstances(freeThread) 
      .FilterString = "(objectCategory=computer)" 
      If Not IntegratedAuthentication Then 
       .UserID = UserID 
       .Password = Password 
      End If 
      .PageSize = 5 
      .PropertiesToLoad = New String() {"cn", "name", "distinguishedName", "dNSHostName", "objectCategory", "objectGUID"} 
     End With 

     ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf compSearchInstances(freeThread).FindComputers), threadParams) 

     'FindComputers(result) 'Search for computer objects in the current OU 

     Dim childNode As New TreeNode(CStr(result.Properties("name")(0))) 
     childNode.Name = result.Path 
     childNode.Tag = result.Properties("objectGUID")(0) 'New Object() {} 
     SearchSub(result, childNode) 
     node.Nodes.Add(childNode) 
     ouResultCount += 1 
     RaiseEvent OUResultFound(ouResultCount) ', pcResultCount) 
    Next 

    Return node 

#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Function 

End Class 

Public Class ComputerSearcher 

'Removed properties and events etc 

Public Sub FindComputers(ByVal threadParams As Object) 
#If Not Debug Then 
    Try 
#End If 

    _doneEvent.Reset() 'Signal that the thread is working 

    System.Diagnostics.Debug.Print("Computer search thread " + threadParams(1).ToString + " is starting") 

    Dim parent As SearchResult = threadParams(0) 

    Dim subEntry As New DirectoryEntry(parent.Path) 

    If Not IntegratedAuthentication Then 
     subEntry.Username = UserID 
     subEntry.Password = Password 
    End If 

    Dim searcher As New DirectorySearcher(subEntry) 
    searcher.PropertiesToLoad.AddRange(PropertiesToLoad) 
    searcher.SearchScope = SearchScope 
    searcher.PageSize = PageSize 
    searcher.ServerTimeLimit = New TimeSpan(0, 10, 0) 
    searcher.Filter = FilterString 

    Dim queryResults As SearchResultCollection 
    queryResults = searcher.FindAll() 

    Dim result As SearchResult 
    For Each result In queryResults 
     pcResultCount += 1 

     Dim dNSHostName As String 
     If result.Properties.Contains("dNSHostName") Then 'If the computer object has a value in dNSHostName (FQDN) store it else store the basic name 
      dNSHostName = result.Properties("dNSHostName")(0) 
     Else 
      dNSHostName = result.Properties("name")(0) 
     End If 

     RaiseEvent ComputerFound(result.Properties("name")(0), dNSHostName, result.Path, result.Properties("objectGUID")(0).ToString) 
     RaiseEvent CompResultFound(pcResultCount) '### TO DO: Rename event to CompIncrementResult 

    Next 

    System.Diagnostics.Debug.Print("Computer search thread " + threadParams(1).ToString + " is ending") 
    _doneEvent.Set() 'Signal that the thread is finished 

#If Not Debug Then 
    Catch Ex as Exception 
     MsgBox(ex.Message, MsgBoxStyle.Critical) 
    End Try 
#End If 

End Sub 
End Class 
+0

的關鍵很可能會在你沒有提供的代碼,即事件'ComputerFound'。我假設你將數據傳回給它,這可能會把它們放在一個清單中,這個清單可能每次都被清除,或者沒有正確確定範圍,所以每個清單都是它自己的實例,並且當你看清清單時,它是空的,因爲它是一個新的實例。只是一個猜測。 – Steve 2014-09-24 21:42:12

+0

感謝您的回覆。如果需要,我可以提供更多代碼,但應該在問題中說明,對不起。所以我不會「認爲」它是我所提供的以外的任何東西,但也許這就是我錯過它的原因。如果你需要更多的代碼,請讓我知道哪些功能,我會在早上發佈。非常感謝。 – Daniel 2014-09-24 22:01:46

回答

0

我終於發現我的錯誤,就像我認爲這是一些愚蠢的盯着我直直的在臉上。在StartSearch()和SubSearch()的代碼的以下部分中,我忘記了設置SearchScope。

With compSearchInstances(freeThread) 
    .FilterString = "(objectCategory=computer)" 
    If Not IntegratedAuthentication Then 
     .UserID = UserID 
     .Password = Password 
    End If 
    .PageSize = 5 
    .PropertiesToLoad = New String() {"cn", "name", "distinguishedName", "dNSHostName", "objectCategory", "objectGUID"} 
End With 

我應該有以下行中有:

.SearchScope = SearchScope 
相關問題