我有一個類,它在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
的關鍵很可能會在你沒有提供的代碼,即事件'ComputerFound'。我假設你將數據傳回給它,這可能會把它們放在一個清單中,這個清單可能每次都被清除,或者沒有正確確定範圍,所以每個清單都是它自己的實例,並且當你看清清單時,它是空的,因爲它是一個新的實例。只是一個猜測。 – Steve 2014-09-24 21:42:12
感謝您的回覆。如果需要,我可以提供更多代碼,但應該在問題中說明,對不起。所以我不會「認爲」它是我所提供的以外的任何東西,但也許這就是我錯過它的原因。如果你需要更多的代碼,請讓我知道哪些功能,我會在早上發佈。非常感謝。 – Daniel 2014-09-24 22:01:46