因需要从LDAP服务器获取客户的组织架构与人员信息,故对c#下获取轻目录数据做一个总结。
- 已知 客户LDAP服务器设置为每次最大查询1000条数据,组织机构数据共3111条
- 环境
- VS2010+.NET Framework 4
- 引用System.DirectoryServices.dll以及System.DirectoryServices.Protocols.dll
- 选择方案
- DirectoryEntry+DirectorySearcher方式
- LDAPConnction+SearchRequest方式
4.DirectoryEntry+DirectorySearcher方式
- 连接服务器
/*构造LDAP的path*/
string path = string.Format("LDAP://{0}", domainName);
/*连接服务器,生成一个DirectoryEntry对象*/
DirectoryEntry domain = new DirectoryEntry(path,userName,userPwd,AuthenticationTypes.Secure);
- 获取数据
/*在domain中查找到要查询的OU节点,并返回该节点的DirectoryEntry对象*/
DirectoryEntry needFindOU = domain.Children.Find("OU="+OUName);
/*根据上一步找到的节点DirectoryEntry对象以及要查询的filter条件,生成DirectorySearcher对象*/
DirectorySearcher mySearch = new DirectorySearcher(needFindOU,filter);
/*设置搜寻范围*/
mySearch.SearchScope = SearchScope.Subtree;
/*由于服务器做了返回数目限制,所以需要进行分页查询。因此设置DirectorySearcher的PageSize属性,以及SizeLimit属性。PageSize为分页搜索中的页大小的值,当其为0时表示不分页。SizeLimit为服务器在搜索中返回的最大对象数量的值,默认值为零,即表示使用由服务器确定的默认大小限制 1000 项。*/
mySearch.PageSize = 100;
mySearch.SizeLimit = 3000;
/*执行查询*/
SearchResultCollection coll = mySearch.FindAll();
/*
对上述PageSize以及SizeLimit多次测试:
pagesize | sizelimit | 返回数据个数 | ||
100 | 1000 | 3111 | ||
100 | 60 | 60 | ||
100 | 100 | 100 | ||
100 | 101 | 3111 |
由此总结出当PageSize < SizeLimit 时可获取到所有数据。当PageSize>=SizeLimit时只能获取到由SizeLimit或服务器限制数目(SizeLimit与服务器限制谁小取谁)的数据。
*/
- 释放占用资源,否则可能造成内存泄露,猜测会造成lsass.exe内存占用增大
执行 DirectoryEntry.Close();
执行 SearchResultCollection.Dispose();
/*MSDN上给出资料: The garbage collector does not release memory for a SearchResultCollection object.Therefore, you must call the Dispose method explicitly to prevent a memory leak.*/
5.LDAPConnction+SearchRequest方式
此种方式没事显示分页获取数据,经查找多方资料并多次测试修改代码,没有成功获取到所有数据,只能获取到服务器限制的1000条数据。这里仍给出代码,希望能给人带来提示。有成功的小伙伴可以联系我,不胜感激。
- 连接服务器
NetworkCredential cre = new NetworkCredential(username, password);
LdapConnection con = new LdapConnection(server);
con.Credential = cre;
con.AuthType = AuthType.Basic;
con.Bind();
- 获取数据
SearchRequest request = new SearchRequest(targetOu, filter, SearchScope.Subtree, null);
PageResultRequestControl page = new PageResultRequestControl(1001);
request.Controls.Add(page);
SearchResponse response = null;
try
{
response = (SearchResponse)con.SendRequest(request, timeOut);
if (response.Controls.Length > 0)
{
foreach (DirectoryControl col in response.Controls)
{
if (col is PageResultResponseControl)
{
pageControl = col as PageResultResponseControl;
break;
}
}
}
data = response.Entries;
if (pageControl != null)
{
((PageResultRequestControl)request.Controls[0]).Cookie = pageControl.Cookie;
}
}
catch (DirectoryOperationException ex)
{
response = (SearchResponse)ex.Response;
data = response.Entries;
if (response.Controls.Length > 0)
{
foreach (DirectoryControl col in response.Controls)
{
if (col is PageResultResponseControl)
{
pageControl = col as PageResultResponseControl;
break;
}
}
}
}
- 备注。经过测试发现SearchResponse.Control中返回的Control为0个。由此若做while循环执行(SearchResponse)con.SendRequest(request, timeOut);并根据返回response.Entries==null || response.Entries.Count==0来做退出条件,则会陷入死循环。因为它始终请求的是第一页的数据。