26

The following code lists some, but not all, Active Directory Groups. Why?

I am trying to list all security groups, distribution groups, computer groups etc. Have I specified the wrong objectClass?

private static void ListGroups()
{
    DirectoryEntry objADAM = default(DirectoryEntry);
    DirectoryEntry objGroupEntry = default(DirectoryEntry);
    DirectorySearcher objSearchADAM = default(DirectorySearcher);
    SearchResultCollection objSearchResults = default(SearchResultCollection);
    SearchResult myResult=null;

    objADAM = new DirectoryEntry(LDAP);
    objADAM.RefreshCache();
    objSearchADAM = new DirectorySearcher(objADAM);
    objSearchADAM.Filter = "(&(objectClass=group))";
    objSearchADAM.SearchScope = SearchScope.Subtree;
    objSearchResults = objSearchADAM.FindAll();

    // Enumerate groups 
    try
    {
        fileGroups.AutoFlush = true;
        if (objSearchResults.Count != 0)
        {
            foreach (SearchResult objResult in objSearchResults)
            {
                myResult = objResult;
                objGroupEntry = objResult.GetDirectoryEntry();
                Console.WriteLine(objGroupEntry.Name);
                fileGroups.WriteLine(objGroupEntry.Name.Substring(3));
            }
        }
        else
        {
            throw new Exception("No groups found");
        }  
    } 
    catch (PrincipalException e)
    {
        fileErrorLog.AutoFlush = true;
        fileErrorLog.WriteLine(e.Message + " " + myResult.Path);
    }
    catch (Exception e)
    {
        throw new Exception(e.Message);
    }
}
ekad
  • 14,436
  • 26
  • 44
  • 46
cymorg
  • 437
  • 1
  • 8
  • 15

6 Answers6

66

If you're on .NET 3.5 or newer, you can use a PrincipalSearcher and a "query-by-example" principal to do your searching:

// create your domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// define a "query-by-example" principal - here, we search for a GroupPrincipal 
GroupPrincipal qbeGroup = new GroupPrincipal(ctx);

// create your principal searcher passing in the QBE principal    
PrincipalSearcher srch = new PrincipalSearcher(qbeGroup);

// find all matches
foreach(var found in srch.FindAll())
{
    // do whatever here - "found" is of type "Principal" - it could be user, group, computer.....          
}

If you haven't already - absolutely read the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 which shows nicely how to make the best use of the new features in System.DirectoryServices.AccountManagement

Jim
  • 2,034
  • 1
  • 22
  • 43
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 5
    I would encapsulate `PrincipalContext`, `GroupPrincipal`, and `PrincipalSearcher` in using blocks since they are disposable. – David Bentley Sep 22 '17 at 14:07
2
DirectoryEntry entry = new DirectoryEntry("ldap://ldap.gaurangjadia.com", "scott", "tiger");

DirectorySearcher dSearch = new DirectorySearcher(entry);
dSearch.Filter = "(&(objectClass=group))";
dSearch.SearchScope = SearchScope.Subtree;

SearchResultCollection results = dSearch.FindAll();

for (int i = 0; i < results.Count; i++) {
    DirectoryEntry de = results[i].GetDirectoryEntry();

    //TODO with "de"
}
Gaurang Jadia
  • 1,516
  • 15
  • 18
  • This did not give me the right results, but marc_s solution did. – JohnB Oct 11 '18 at 22:31
  • 1
    Be careful with this as stated in [this blogpost](https://www.gabescode.com/active-directory/2018/12/15/better-performance-activedirectory.html), the `GetDirectoryEntry()` will load **ALL** properties, including the ones you don't need – JohannesB Mar 04 '20 at 14:51
2

Try filter "(objectcategory=group)" Found solution here

Sergey Vedernikov
  • 7,609
  • 2
  • 25
  • 27
0

I tried this and it worked

    public ArrayList GetAllGroupNames(string ipAddress, string ouPath)
    {
        DirectorySearcher deSearch = new DirectorySearcher();
        deSearch.SearchRoot = GetRootDirectoryEntry(ipAddress, ouPath);
        deSearch.Filter = "(&(objectClass=group))";
        SearchResultCollection results = deSearch.FindAll();
        if (results.Count > 0)
        {
            ArrayList groupNames = new ArrayList();

            foreach (SearchResult group in results)
            {
                var entry = new DirectoryEntry(group.Path, UserName, Password);
                string shortName = entry.Name.Substring(3, entry.Name.Length - 3);
                groupNames.Add(shortName);
            }

            return groupNames;
        }
        else
        {
            return new ArrayList();
        }
    }

    private DirectoryEntry GetRootDirectoryEntry(string ipAddress, string domainPath, string username, string password)
    {
        var ldapPath = "LDAP://" + ipAddress + "/" + domainPath;
        return new DirectoryEntry(ldapPath, username, password, AuthenticationTypes.Secure);
    }
Dinesh Kumar P
  • 1,128
  • 2
  • 18
  • 32
0

To retrieve a set of results that is larger than 1000 items, you must set SizeLimit to its default value (zero) and set PageSize to a value that is less than or equal to 1000.

objSearchADAM.PageSize = 1000;

Khawar
  • 1
  • 1
0

you can get the all ad group details by the below powershell and if you want particular Name against of AD Group then write filter instead of *

Get-ADGroup -Filter * -properties * | Export-csv c:\csv\new.csv