ActiveDirectory,Range不使用DirectorySearcher更改结果

时间:2012-09-04 20:46:57

标签: c# active-directory

所以我基本上试图枚举AD的结果,由于某种原因我无法取下新的结果,这意味着它不断拉动前1500个结果,即使我告诉它我想要一个额外的范围。

有人能指出我犯错误的地方吗?代码永远不会脱离循环,但更重要的是,即使我说我想要用户1500-3000,它也会吸引用户1-1500。

uint rangeStep = 1500;   
uint rangeLow = 0;   
uint rangeHigh = rangeLow + (rangeStep - 1);   
bool lastQuery = false;   
bool quitLoop = false;   

do   
{                       
    string attributeWithRange;   
    if (!lastQuery)   
    {   
        attributeWithRange = String.Format("member;Range={0}-{1}", rangeLow, rangeHigh);   
    }   
    else   
    {   
        attributeWithRange = String.Format("member;Range={0}-*", rangeLow);   
    }   
    DirectoryEntry dEntryhighlevel = new DirectoryEntry("LDAP://OU=C,OU=x,DC=h,DC=nt");   
    DirectorySearcher dSeacher = new DirectorySearcher(dEntryhighlevel,"(&(objectClass=user)(memberof=CN=Users,OU=t,OU=s,OU=x,DC=h,DC=nt))",new string[] {attributeWithRange});   
    dSeacher.PropertiesToLoad.Add("givenname");   
    dSeacher.PropertiesToLoad.Add("sn");   
    dSeacher.PropertiesToLoad.Add("samAccountName");   
    dSeacher.PropertiesToLoad.Add("mail");   
    dSeacher.PageSize = 1500;   
    SearchResultCollection resultCollection = resultCollection = dSeacher.FindAll();   
    dSeacher.Dispose();   

    foreach (SearchResult userResults in resultCollection)   
    {   

        string Last_Name = userResults.Properties["sn"][0].ToString();   
        string First_Name = userResults.Properties["givenname"][0].ToString();   
        string userName = userResults.Properties["samAccountName"][0].ToString();   
        string Email_Address = userResults.Properties["mail"][0].ToString();   
        OriginalList.Add(Last_Name + "|" + First_Name + "|" + userName + "|" + Email_Address);   
    }   
    if(resultCollection.Count == 1500)   
    {   
        lastQuery = true;   
        rangeLow = rangeHigh + 1;   
        rangeHigh = rangeLow + (rangeStep - 1);   
    }   
    else   
    {   
        quitLoop = true;   
    }   

}   
while (!quitLoop);

2 个答案:

答案 0 :(得分:0)

你混淆了两个导致你麻烦的概念。这是SO论坛上的常见问题解答,所以我可能应该在博客上试着清理一下。

首先让我解释一下概念,然后在概念出现后更正代码。

概念一是获取大量对象。当您获取大量对象时,您需要批量请求它们。这通常称为“分页”结果。执行此操作时,您将获得一个分页cookie,并可以在后续搜索中传回分页控件,以便在每次传递时获得“页面值”的结果。

第二个概念是从单个属性中获取大量值。一个简单的例子是从组中读取成员属性(例如:对该组进行基本搜索)。这称为“远程检索”。在这种搜索模式中,您正在针对大型属性(如成员)对该对象进行基本搜索,并在每次传递搜索时询问值的“范围”。

上面的代码混淆了这些概念。您正在进行成员范围逻辑,就像您正在进行范围检索一样,但实际上您正在进行构造以返回大量对象(如分页搜索)的搜索。这就是为什么你一遍又一遍地得到相同的结果。

要解决此问题,您需要先选择一种方法。 :)我建议对组对象进行范围检索,并在范围内要求大成员属性。这将使您获得该组中的所有成员。 如果沿着这条路走下去,你会注意到你不能要求这些值的属性。您获得的唯一值是成员列表,然后您可以搜索它们。如果您选择继续使用上面的分页搜索,那么您最终会切换到分页搜索。

如果您选择坚持使用分页搜索,那么您需要:

  • 摆脱范围逻辑,以及1500
  • 的所有提及
  • 将页面大小设置为1000
  • 使用您的API
  • 查找如何进行分页搜索(使用页面搜索控件),而不是测距

如果您选择范围,您将从这样的memberOf搜索切换到搜索表单:         a)范围:基数         b)过滤器:(objectclass = )         c)基本DN:OU = C,OU = x,DC = h,DC = nt         d)属性:成员;范围= 0 - ...然后,当您获取值的范围时,您将增加0(即,对每个后续值范围反复搜索,仅将0更改为后续整数) 您在我的逻辑中会注意到的其他尼特:   - 我没有设置页面大小...你没有进行分页搜索,所以没关系。   - 我不会在这里硬编码值1500。没关系。知道甚至计算这个都没有价值。关键是你要求0- *(即全部),你得到1500,那么你说1500- ,然后是3000 - ,依此类推。你不需要知道范围大小,只需要你到目前为止给出的范围。

我希望这完全回答它......

以下是根据我的评论进行分页搜索的代码片段(这是您需要使用System.DirectoryServices.Protocols命名空间类进行的操作,沿着您上面开始的逻辑路径(分页搜索,而不是远程检索)):

        string searchFilter = "(&(objectClass=user)(memberof=CN=Users,OU=t,OU=s,OU=x,DC=h,DC=nt))";
        string baseDN = "OU=C,OU=x,DC=h,DC=nt";
        var scope = SearchScope.Subtree;
        var attributeList = new string[] { "givenname", "sn", "samAccountName", "mail" };
        PageResultRequestControl pageSearchControl = new PageResultRequestControl(1000);
        do
        {
            SearchRequest sr = new SearchRequest(baseDN, searchFilter, scope, attributeList);
            sr.Controls.Add(pageSearchControl);

            var directoryResponse = ldapConnection.SendRequest(sr);
            if (directoryResponse.ResultCode != ResultCode.Success)
            {
                // Handle error
            }

            var searchResponse = (SearchResponse)directoryResponse;

            pageSearchControl = null; // Reset!
            foreach (var control in searchResponse.Controls)
            {
                if (control is PageResultResponseControl)
                {
                    var prrc = (PageResultResponseControl)control;
                    if (prrc.Cookie.Length > 0)
                    {
                        pageSearchControl = new PageResultRequestControl(prrc.Cookie);
                    }
                }
            }

            foreach (var entry in searchResponse.Entries)
            {
                // Handle the search result entry
            }
        } while (pageSearchControl != null);

答案 1 :(得分:-1)

您的问题是由循环中创建目录搜索器的新对象引起的。每次都会有新的对象,将采取前1500条记录。在循环中创建searher实例,并为所有查询使用相同的实例。