通过 System.DirectoryServices (VB.NET) 扫描 GlobalCatalog 偶尔会引发错误
Scanning GlobalCatalog via System.DirectoryServices (VB.NET) throws occasional error
Objective:创建一个简单的 VB.NET 应用程序以使用基本过滤器扫描 GlobalCatalog,仅限于预定义的属性并将结果写入文本文件。
方法:下面的现有代码 - 这个 "works" 但偶尔会抛出异常:"System.DirectoryServices.SearchResultCollection.ResultsEnumerator.MoveNext() : More data is available"
一些浏览让我认为(欢迎更正)问题是由于尝试通过 DirectorySearcher 检索大量记录(在我的例子中大约 400k)引起的,尽管结果是分页的,并且解决方案可能是将现有的 System.DirectoryServices 方法切换为使用 System.DirectoryServices.Protocols 的方法。参见 this SO thread leading to this article。
但是,我发现的所有回复,包括上面的链接和广泛搜索的其他链接,都只提供 C# 中的代码片段,而且似乎只查询单个记录(例如,根据特定的可分辨名称检索属性或登录)
我需要使用 VB.NET 尽可能快速高效地检索大量记录。我喜欢 DirectoryServices 方法,因为它让我可以轻松处理 GlobalCatalog,而无需提供域或密码 - 我可以直接跳转到搜索器并开始指定过滤器和属性。它通常可以工作 - 但我每次都需要它工作。
任何人都可以建议我如何调整此代码以规避偶尔的异常并以最佳方式提取我需要的所有数据吗?
Imports System.DirectoryServices
Public Sub ScanGlobalCatalog()
Dim searcher As DirectorySearcher = ActiveDirectory.Forest.GetCurrentForest.FindGlobalCatalog.GetDirectorySearcher
Try
With searcher
.Filter = "(&(|(objectClass=user)(objectClass=group))(proxyAddresses=*))"
.PageSize = 1000
.SearchScope = SearchScope.Subtree
.CacheResults = False
.PropertiesToLoad.Add("sAMAccountName")
.PropertiesToLoad.Add("distinguishedName")
.PropertiesToLoad.Add("displayName")
.PropertiesToLoad.Add("proxyAddresses")
End With
For Each result As SearchResult In searcher.FindAll()
Dim properties As ResultPropertyCollection = result.Properties
Dim sAMAccountName As ResultPropertyValueCollection = properties("sAMAccountName")
Dim distinguishedName As ResultPropertyValueCollection = properties("distinguishedName")
Dim displayName As ResultPropertyValueCollection = properties("displayName")
Dim proxyAddresses As ResultPropertyValueCollection = properties("proxyAddresses")
' Check / process / write each property to the output file...
Next
Catch ex As Exception
' Do something...
End Try
End Sub
谢谢晚祷!
如图所示添加,它似乎不再发生(我相信将 .SizeLimit 设置为 0 等同于 'limitless' 但同样,欢迎那些比我知识渊博的人进行更正...... )
With searcher
.Filter = "(&(|(objectClass=user)(objectClass=group))(proxyAddresses=*))"
.PageSize = 1000
.SizeLimit = 0
.SearchScope = SearchScope.Subtree
.CacheResults = False
.PropertiesToLoad.Add("sAMAccountName")
.PropertiesToLoad.Add("distinguishedName")
.PropertiesToLoad.Add("displayName")
.PropertiesToLoad.Add("proxyAddresses")
End With
在过去 20 小时左右的时间里,运行以 15 分钟的间隔将脚本作为服务使用,我可以在事件日志中看到 5 或 6 个 'fails' - 但是,以前这个会导致致命终止(服务会简单地停止);现在它只是报告异常并在下一次迭代中重试。
故障聚集在一起(同一小时/一个半小时内连续 'runs')并且相同的服务 运行 现在大约 15 小时不间断且无错误,引导我怀疑这些失败可能与服务器上进行的某种维护或某种记录更新中途抛出异常同时发生。再次欢迎您对此行为提出任何见解或意见。
但我可以忍受这样的 'occasional' 异常,只要脚本通常 运行 没问题并且不会永久性地崩溃 if/when 它们出现。
再次感谢 Vesper 的建议!
Objective:创建一个简单的 VB.NET 应用程序以使用基本过滤器扫描 GlobalCatalog,仅限于预定义的属性并将结果写入文本文件。
方法:下面的现有代码 - 这个 "works" 但偶尔会抛出异常:"System.DirectoryServices.SearchResultCollection.ResultsEnumerator.MoveNext() : More data is available"
一些浏览让我认为(欢迎更正)问题是由于尝试通过 DirectorySearcher 检索大量记录(在我的例子中大约 400k)引起的,尽管结果是分页的,并且解决方案可能是将现有的 System.DirectoryServices 方法切换为使用 System.DirectoryServices.Protocols 的方法。参见 this SO thread leading to this article。
但是,我发现的所有回复,包括上面的链接和广泛搜索的其他链接,都只提供 C# 中的代码片段,而且似乎只查询单个记录(例如,根据特定的可分辨名称检索属性或登录)
我需要使用 VB.NET 尽可能快速高效地检索大量记录。我喜欢 DirectoryServices 方法,因为它让我可以轻松处理 GlobalCatalog,而无需提供域或密码 - 我可以直接跳转到搜索器并开始指定过滤器和属性。它通常可以工作 - 但我每次都需要它工作。
任何人都可以建议我如何调整此代码以规避偶尔的异常并以最佳方式提取我需要的所有数据吗?
Imports System.DirectoryServices
Public Sub ScanGlobalCatalog()
Dim searcher As DirectorySearcher = ActiveDirectory.Forest.GetCurrentForest.FindGlobalCatalog.GetDirectorySearcher
Try
With searcher
.Filter = "(&(|(objectClass=user)(objectClass=group))(proxyAddresses=*))"
.PageSize = 1000
.SearchScope = SearchScope.Subtree
.CacheResults = False
.PropertiesToLoad.Add("sAMAccountName")
.PropertiesToLoad.Add("distinguishedName")
.PropertiesToLoad.Add("displayName")
.PropertiesToLoad.Add("proxyAddresses")
End With
For Each result As SearchResult In searcher.FindAll()
Dim properties As ResultPropertyCollection = result.Properties
Dim sAMAccountName As ResultPropertyValueCollection = properties("sAMAccountName")
Dim distinguishedName As ResultPropertyValueCollection = properties("distinguishedName")
Dim displayName As ResultPropertyValueCollection = properties("displayName")
Dim proxyAddresses As ResultPropertyValueCollection = properties("proxyAddresses")
' Check / process / write each property to the output file...
Next
Catch ex As Exception
' Do something...
End Try
End Sub
谢谢晚祷!
如图所示添加,它似乎不再发生(我相信将 .SizeLimit 设置为 0 等同于 'limitless' 但同样,欢迎那些比我知识渊博的人进行更正...... )
With searcher
.Filter = "(&(|(objectClass=user)(objectClass=group))(proxyAddresses=*))"
.PageSize = 1000
.SizeLimit = 0
.SearchScope = SearchScope.Subtree
.CacheResults = False
.PropertiesToLoad.Add("sAMAccountName")
.PropertiesToLoad.Add("distinguishedName")
.PropertiesToLoad.Add("displayName")
.PropertiesToLoad.Add("proxyAddresses")
End With
在过去 20 小时左右的时间里,运行以 15 分钟的间隔将脚本作为服务使用,我可以在事件日志中看到 5 或 6 个 'fails' - 但是,以前这个会导致致命终止(服务会简单地停止);现在它只是报告异常并在下一次迭代中重试。
故障聚集在一起(同一小时/一个半小时内连续 'runs')并且相同的服务 运行 现在大约 15 小时不间断且无错误,引导我怀疑这些失败可能与服务器上进行的某种维护或某种记录更新中途抛出异常同时发生。再次欢迎您对此行为提出任何见解或意见。
但我可以忍受这样的 'occasional' 异常,只要脚本通常 运行 没问题并且不会永久性地崩溃 if/when 它们出现。
再次感谢 Vesper 的建议!