Active Directory: Get All Users using C# with Linq To Active Directory

Posted by OmegaMan at January 14, 2009

Category: Linq, Security

I began working on a website which had the requirement of getting all users from Active Directory/LDAP.  I began working on a solution by searching the web. When I ran across a tool LINQ to Active Directory which allows one to use Linq against Active Directory. I found that code to be quite helpful in my task. This article discusses how to use the tool and additional code changes I created to make the tool even more specialized and less prone to memory leaks.

Steps: Get all users.

  1. Download the latest Linq to AD from codeplex LINQ to Active Directory. It expands a demo project and the main library project BdsSoft.DirectoryServices.Linq.
  2. Create a new blank solution and add the BdsSoft.DiretoryServices.Linq  project into it.
  3. Create a new project to consume the library.
  4. In the new project add these references
    1: to the BdsSoft.DirectoryServices
    2: System.DirectoryServices
    3: The com object Active DS Type library:

    Active DS Type Library in the COM tab

  5. Now we have to create our own entity. Basically it is a class where the properties are simply the name of the target LDAP categories. Here are the usings which will be needed:
    using ActiveDs;
    using BdsSoft.DirectoryServices.Linq;
    using System.Linq.Expressions;
    using System.DirectoryServices;
  6. Here is the entity class user which will hold each item:
    [DirectorySchema( "user", typeof( IADsUser ) )]
    class User
    {
        public string Name { get; set; }
    
        public string sAMAccountName { get; set; }
    
        public string objectCategory { get; set; }
    
        public string mail { get; set; }
    
        public string Description { get; set; }
    
        [DirectoryAttribute( "PasswordLastChanged", DirectoryAttributeType.ActiveDs )]
        public DateTime PasswordLastSet { get; set; }
    
        [DirectoryAttribute("distinguishedName")]
        public string Dn { get; set; }
    
        [DirectoryAttribute("memberOf")]
        public string[] Groups { get; set; }
    
    }
  7. The above class uses attributes to inform the Linq To AD library how to handle the entity and if need be change names of each of the properties of the class.
  8. Use this code to access AD from a console app, placing your AD server in the below code:
    static void Main( string[] args )
    {
    
        IEnumerable<User> users = GetADUsers();
    
        Console.WriteLine( "Users: " + users.Count().ToString() );
    
    }
    
    static DirectoryEntry ROOT = new DirectoryEntry( "LDAP://MyADDomainLocation.com" );
    
    private static IEnumerable<User> GetADUsers()
    {
        IEnumerable<User> users;
    
        var usersDS = new DirectorySource<User>( ROOT, SearchScope.Subtree );
    
                users = from usr in usersDS
                        where usr.Name == "A*" // FIlter A then any character(s)
                        select usr;
    
         users = users.OrderBy( user => user.Name ).ToList(); // Sort them alphabetically by name.
    
        return users;
    }

That will get you up and running but there are three problems with the library which you may run into.

  1. The code uses DirectorySearcher..::.FindAll Methodwhich states in the remarks that improper usage may result in a memory leak.
  2. The action even though user is stated, at least in my domain returned non users. A different LDAP category needs to be used.
  3. Doesn’t handle specific LDAP command to ignore inactive users.

I rectify those issues and will detail it in a future post.

Share

9 Comments

  1. JD says

    I was just going to give you hell today for no posts, and went and posted.

    Keep posting about Linq, I’ll figure it out eventually. Your examples are very useful.

    Reply
  2. Paul says

    Very helpful article on this difficult topic, learnt a bit of linq as well. Thanks Mate.

    Reply
  3. Kaleem Khan says

    I found this very useful but I got an exception ‘Could not load file or assembly ‘Interop.ActiveDs’ in file DirectorySources.

    I just want to mentione that when I added the COM reference, it was from C:\WINDOWS\SysWOW64 may be because I’m using 64 bit. I tried to add the safe reference from System32 folder but that doesnt seem to work. I hope you can help me with this. Thanks.

    Reply
  4. Marc says

    Hello, any information on how to get all Active Directory groups the active user is in would be very helpful.

    Thank you

    Reply
  5. Nick says

    Your note that says you rectify “those” issues (specifically, filtering inactive users) got me excited: I would love to see how you accomplish this. Thanks.

    Reply
    • OmegaMan says

      I need to look at my notes and do an update Nick. Sorry for the delay.

      Reply
  6. sbaker says

    @OmegeMan,

    You may want to check out http://adlinq.codeplex.com. It supports more of the Linq methods like Skip, Take, First, Last, Single and more as well as Child property collections like user.Groups.

    Thanks and great post!

    Reply
  7. Boniface says

    You tutorial is great, wanted to ask about the second bit of code, does it reside in the same class as the user class or its own class. I will appreciate a full working class of the second code.. thanks

    Reply
    • OmegaMan says

      It is a static method and does not have to reside in the user class unless you want it too.

      Reply

Leave a comment

(required)
(required) (will not be published)

This site uses Akismet to reduce spam. Learn how your comment data is processed.