首页 > 解决方案 > 当用户没有组时,在 Active Directory 中搜索特定组的成员失败

问题描述

以下代码应该遍历活动目录中的所有用户并找到特定组中的每个人。一旦获得用户,它会将他们添加到数据表中,该数据表将成为最终导出到 Excel 的 gridview 的源。

但是,在运行和单步执行时,我注意到它在某个没有组的用户上停止了。我尝试添加一个条件语句来跳过该实例,但它不起作用,当它找到没有组的用户时,代码仍然停止运行。

有人可以告诉我我可以做些什么不同的事情吗?警告:这是我继承的一个遗留站点,对活动目录知之甚少,并且是一个新手 vb 编码器。

Dim entry As DirectoryEntry = New DirectoryEntry("LDAP://DOMAIN.EDU", "USERNAME", "PASSWORD", AuthenticationTypes.Secure)
    Dim search As DirectorySearcher = New DirectorySearcher(entry) With {
        .Filter = "(&(objectCategory=User)(objectClass=person))",
        .PageSize = 4000
    }
    search.PropertiesToLoad.Add("userPrincipalName").ToString
    search.PropertiesToLoad.Add("name").ToString
    Dim mySearchResultColl As SearchResultCollection = search.FindAll
    Dim results As DataTable = New DataTable
    results.Columns.Add("User ID")        
    results.Columns.Add("Full Name")
    Dim CurrRow = 0

    For Each sr As SearchResult In mySearchResultColl

        Dim dr As DataRow = results.NewRow
        Dim de As DirectoryEntry = sr.GetDirectoryEntry
        !!!! line below is the problem !!!!
        If de.Properties("memberOf") IsNot Nothing AndAlso de.Properties("memberOf").Value.ToString = "CN=MYGROUP,OU=Security Groups,OU=Students,DC=DOMAIN,DC=edu" Then 
            dr("User ID") = de.Properties("userPrincipalName").Value           
            dr("Full Name") = de.Properties("name").Value
            results.Rows.Add(dr)
            de.Close
        End If
    Next

    gvNot.DataSource = results
    gvNot.DataBind()
    gvNot.Visible = True
    gvAgreed.Visible = False
    ExportToExcel("notagreed", gvNot)

标签: vb.netactive-directory

解决方案


我不确定您所说的“停止”是什么意思,但您可以对其进行更改,使其性能更好并解决您遇到的任何问题。

  1. 这个循环将永远持续下去,因为您必须检查域中的每个用户。如果您只想要特定组中的用户,那么您可以通过只询问该组的成员来加快速度。您可以通过在memberOf属性的查询中添加条件来做到这一点。这样,您只会得到您关心的结果。

(请注意,如果您的林中有多个域,则用于查找成员可能无法按您希望的方式工作。我在这里memberOf写过。但如果您只有一个域,那就没问题了。)

  1. 在循环中,不要DirectoryEntry为每个结果创建一个,因为这将迫使它返回 AD 并再次请求对象的属性,即使您已经在搜索结果中获得了所需的内容。因此,请改用SearchResult对象中的值。

  2. 文档SearchResultCollection说:

由于实现限制,SearchResultCollection 类在垃圾回收时无法释放其所有非托管资源。为防止内存泄漏,您必须在不再需要 SearchResultCollection 对象时调用 Dispose 方法。

所以你应该把它放在一个Using子句中。

  1. 我也不确定你为什么ToStringPropertiesToLoad.Add不使用返回值时调用。你可以删除它。

这一切都在一起:

Dim entry As DirectoryEntry = New DirectoryEntry("LDAP://DOMAIN.EDU", "USERNAME", "PASSWORD", AuthenticationTypes.Secure)
Dim search As DirectorySearcher = New DirectorySearcher(entry) With {
    .Filter = "(&(objectCategory=User)(objectClass=person)(memberOf=CN=MYGROUP,OU=Security Groups,OU=Students,DC=DOMAIN,DC=edu))",
    .PageSize = 4000
}
search.PropertiesToLoad.Add("userPrincipalName")
search.PropertiesToLoad.Add("name")

Dim results As DataTable = New DataTable
results.Columns.Add("User ID")        
results.Columns.Add("Full Name")
Dim CurrRow = 0

Using mySearchResultColl As SearchResultCollection = search.FindAll
    For Each sr As SearchResult In mySearchResultColl

        Dim dr As DataRow = results.NewRow
        dr("User ID") = sr.Properties("userPrincipalName")(0)
        dr("Full Name") = sr.Properties("name")(0)
        results.Rows.Add(dr)
    Next
End Using

gvNot.DataSource = results
gvNot.DataBind()
gvNot.Visible = True
gvAgreed.Visible = False
ExportToExcel("notagreed", gvNot)

我没有看到您CurrRow在任何地方使用它,但我留下了它以防您在此处未显示的其他代码中使用它。


推荐阅读