Wednesday, February 03, 2010

GroupPrincipal GetGroups() does not work as "I" expected.

System.DirectoryServices.AccountManagement Namespace contains the GroupPrincipal object which, according to documentation, returns the groups of which the principal is directly a member.

I have found that this method is unreliable in a large domain and many times does not return any groups at all. Instead try the snippet below to return a list
and compare the DN's. This also gets past the limitation imposed by Active Directory Windows 2000 (1000 items) and Windows Server 2003 (1500 items) LDAP administration limits. This code is not my own work, just a modification of others to suit my needs.

There is a nice example of how to get around this here
http://msdn.microsoft.com/en-us/library/ms180907.aspx.

All this is, is a method derived from the solution in the link above and used to get around the issue I have. Also I needed a place to remind myself how to do it, so here it is.


example usage:
List members = LdapSearch.GetMemberList(grp2.GetUnderlyingObject() as DirectoryEntry);
if (!members.Contains(gNestedGrp.DistinguishedName))

{
((DO SOMETHING))

}

----------------------------------------------------------------------------------

///
/// group member enumeration, simple and fast for large AD groups
///

public static List GetMemberList(DirectoryEntry deGroup)
{
List list = new List();
DirectoryEntry entry = deGroup;

uint rangeStep = 1000;
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);
}
using (DirectorySearcher searcher = new DirectorySearcher(entry))
{
searcher.Filter = "(objectClass=*)";

searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add(attributeWithRange);
SearchResult results = searcher.FindOne();
foreach (string res in results.Properties.PropertyNames)
{
//list the property names
System.Diagnostics.Debug.WriteLine(res.ToString());
}

if (results.Properties.Contains(attributeWithRange))
{
foreach (object obj in results.Properties[attributeWithRange])
{
//Console.WriteLine(obj.GetType());
if (obj.GetType().Equals(typeof(System.String)))
{
}
else if (obj.GetType().Equals(typeof(System.Int32)))
{
}
//Console.WriteLine(obj.ToString());
list.Add(obj.ToString());
}
if (lastQuery)
{
quitLoop = true;
}
}
else
{
if (lastQuery == false)
{ lastQuery = true; }
else
{ quitLoop = true; }
}
if (!lastQuery)
{
rangeLow = rangeHigh + 1;
rangeHigh = rangeLow + (rangeStep - 1);
}
}
}
while (!quitLoop);

return list;
}

0 comments: