c# - DirectoryServices - 不正确的组成员计数

时间:2017-10-02 23:30:41

标签: c# .net

我确信有一个非常简单的解释,但我找不到它。我正在尝试计算我们域中所有组的成员数,并且下面的代码大部分都可用,但是有一个特定的组我无法准确计算。该组有超过1000名成员,但由于某种原因,下面的代码保持返回0.这是由于成员的数量?该集团没有什么特别之处,它只是一个普通的全球安全组织。

DirectoryEntry context = new DirectoryEntry("LDAP://MyDomain.test");
DirectorySearcher searchGroups = new DirectorySearcher(context);
searchGroups.SearchScope = SearchScope.Subtree;
searchGroups.PageSize = 500;
searchGroups.Filter = "objectClass=group";
searchGroups.PropertiesToLoad.Add("member");

SearchResultCollection searchGroupsResults = searchGroups.FindAll();

foreach (SearchResult group in searchGroupsResults)
{
    Console.WriteLine("Group: " + group.Properties["name"][0].ToString() + " - Member Count: " + group.Properties["member"].Count.ToString());
}

返回:
组:MyGroup1 - 成员数:0

组:MyGroup2 - 成员人数:861

组:MyGroup3 - 成员人数:920

组:MyGroup4 - 会员数:9 ....

3 个答案:

答案 0 :(得分:1)

如果你查询一个大组,并且微软在C ++中演示了一个复杂的算法,那就复杂得多了,

https://msdn.microsoft.com/en-us/library/aa367017(v=vs.85).aspx

有人翻译成.NET

https://itconnect.uw.edu/wares/msinf/authn/ldap/enumerate-large-groups/

...
 using System.DirectoryServices;
 ...

/// <summary>
 /// Determines whether or not the specified user is a member of the group.
 /// </summary>
 /// <param name="UserDN">A System.String containing the user's distinguished name (DN).</param>
 /// <param name="Group">A System.DirectoryServices.DirectoryEntry object of the target group.</param>
 private Boolean IsMemberOfLargeGroup( String UserDN, DirectoryEntry Group )
 {
 Boolean userFound = false;
 Boolean isLastQuery = false;
 Boolean exitLoop = false;
 Int32 rangeStep = 1500;
 Int32 rangeLow = 0;
 Int32 rangeHigh = rangeLow + ( rangeStep - 1 );
 String attributeWithRange;

DirectorySearcher groupSearch = new DirectorySearcher( Group );
 SearchResult searchResults;

groupSearch.Filter = "(objectClass=*)";

do
 {
 if( !isLastQuery )
 attributeWithRange = String.Format( "member;range={0}-{1}", rangeLow, rangeHigh );
 else
 attributeWithRange = String.Format( "member;range={0}-*", rangeLow );

groupSearch.PropertiesToLoad.Clear();
 groupSearch.PropertiesToLoad.Add( attributeWithRange );

searchResults = groupSearch.FindOne();
 groupSearch.Dispose();

if( searchResults.Properties.Contains( attributeWithRange ) )
 {
 if( searchResults.Properties[ attributeWithRange ].Contains( userDN ) )
 userFound = true;

if( isLastQuery )
 exitLoop = true;
 }
 else
 {
 isLastQuery = true;
 }

if( !isLastQuery )
 {
 rangeLow = rangeHigh + 1;
 rangeHigh = rangeLow + ( rangeStep - 1 );
 }
 }
 while( ! ( exitLoop | userFound ) );

return userFound;
 }

答案 1 :(得分:0)

可能是由于您的searchGroups在收集垃圾时无法释放所有非托管资源,如msnd所述:https://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.findall.aspx

尝试在使用中包装所有内容,或使用Dispose():

using SearchResultCollection searchGroupsResults = searchGroups.FindAll())
{
    foreach (SearchResult group in searchGroupsResults)
    {
        Console.WriteLine("Group: " + group.Properties["name"][0].ToString() + " - Member Count: " + group.Properties["member"].Count.ToString());
    }
}

答案 2 :(得分:0)

谢谢你的帮助。我按照你的建议做了并使用了Dispose()方法,但它没有帮助。我能够通过使用DirectoryEntry而不是SearchResult解决问题。见下文。

DirectoryEntry context = new DirectoryEntry("LDAP://My.Domain.com");
DirectorySearcher searchGroups = new DirectorySearcher(context);
searchGroups.SearchScope = SearchScope.Subtree;
searchGroups.PageSize = 500;
searchGroups.Filter = "objectClass=group";
searchGroups.PropertiesToLoad.Add("name");
searchGroups.PropertiesToLoad.Add("member");

SearchResultCollection searchGroupsResults = searchGroups.FindAll();

foreach (SearchResult group in searchGroupsResults)
{
    DirectoryEntry groupDirectoryEntry = group.GetDirectoryEntry();

    Console.WriteLine("Group: " + group.Properties["name"][0].ToString() + " - Member Count: " + groupDirectoryEntry.Properties["member"].Count.ToString());
}