Link to home
Start Free TrialLog in
Avatar of atomicstorm
atomicstorm

asked on

How to Get a List of Active Directory Members in a Distribution List with C#?

I have been searching through EE and the internet looking for a way to get a list of active directory members based on user input of the specific distribution list.  I've tried many different  combinations; however, all I get is a -532xxxxxxx COM error or 1000+ results (the test distribution list has 1 member in it).  I have attached the code I have so far.

NOTE: I have blacked out the AD location and I understand I am not filtering on anything but I apparently cannot get the LDAP query right.  I am new to LDAP.
Program.cs
--------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
 
namespace ExactTarget_ADFTP
{
    class Program
    {
        static string GetProperty(SearchResult searchResult, string PropertyName)
        {
            if(searchResult.Properties.Contains(PropertyName))
            {
                return searchResult.Properties[PropertyName][0].ToString() ;
            }
            else
            {
                return string.Empty;
            }
        }
 
        static void Main(string[] args)
        {
            XXXXX.BusinessLogic.ExactTarget_ADFTP.FetchAD oLDAP = new XXXXX.BusinessLogic.ExactTarget_ADFTP.FetchAD();
 
            int iCount = 0;
            Console.Write("What is the distribution list name? ");
            string input = Console.ReadLine();
 
            Console.WriteLine("");
            Console.WriteLine(String.Concat("Fetching Information for ", input, "..."));
 
            SearchResultCollection LDAPResultCollection = oLDAP.GetUserInfo(input);
 
            try
            {
                foreach (SearchResult LDAPResult in LDAPResultCollection)
                {
                    iCount += 1;
                    Console.WriteLine(GetProperty(LDAPResult, "cn")); // 
                    Console.WriteLine(GetProperty(LDAPResult, "givenName")); // First
                    Console.WriteLine(GetProperty(LDAPResult, "sn")); // Last
                    Console.WriteLine(GetProperty(LDAPResult, "mail")); // Email Address
                    Console.WriteLine(GetProperty(LDAPResult, "DistinguishedName")); // Group?
                }
            }
            catch (System.Exception)
            {
            }
 
            Console.Write("Program Ended, Count: " + iCount);
            input = Console.ReadLine();
        }
}
 
FetchAD.cs
-----------------------
#region "Imports"
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.Data;
#endregion
 
namespace XXXXX.BusinessLogic.ExactTarget_ADFTP
{
    public class FetchAD
    {
        protected String SPLDAPADDRESS = "xxxxxx.xxxxxx.net";
 
        public SearchResultCollection GetUserInfo(string Distribution)
        {
            try
            {
                string LDAPAddress = String.Format("LDAP://{0}", SPLAPADDRESS);
                DirectoryEntry deLDAP = new DirectoryEntry(LDAPAddress);
                deLDAP.AuthenticationType = AuthenticationTypes.Delegation;
                
                DirectorySearcher mySearcher = new DirectorySearcher(deLDAP, "(objectClass=person)");
 
                return mySearcher.FindAll();
            }
            catch (System.Exception)
            {
                return null;
            }
        }
    }
}

Open in new window

Avatar of Anurag Thakur
Anurag Thakur
Flag of India image

the following ee link shows how to export it to an excel
may be you can find how to export to List
https://www.experts-exchange.com/questions/21311589/Export-Distribution-List-Members-from-Active-Directory-to-Excel.html
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Was just cruising by and saw this question.  I realise this isn't a direct answer to your question but it does work and does list all users in a requested Active Directory - it might give you a good place to start.

If it helps please post a comment on the article - it's my site.  :)

http://digitalformula.net/net-geekery/follow-up-list-active-directory-users-this-time-in-c/

Hey Number5ix :)

I have a few comments if I may, hopefully you don't mind :)

> DirectoryEntry de = resEnt.GetDirectoryEntry();

If you're just listing members you do not need to create a directory entry for each user. It is more efficient (costs less) to retrieve the value from the SearchResult, especially important if we're looking at large result sets.

> "(objectClass=user)"

Because of how Classes are defined this filter will return Computer objects as well (if they appear within the specified sub tree). "(&(objectClass=user)(objectCategory=person))" will return just users, where just "(objectCategory=person)" will return users and contact objects.

Paging: You'll need it enabled if you expect to return more than 1000 results in the query.

Returned attributes, again only applies for large(r) result sets, but it is generally sensible to restrict the Properties loaded into the SearchResult to only those that are actually necessary.

Chris
Nope I don't mind at all - they're good tips.  Thanks!  :)
@Chris-Dent:

The objectCategory=person thing works well.  Your comment about not needing to create a DirectoryEntry is interesting though.  On looking at my code again, how would you do it?  Once you've got the SearchResult objects from mySearcher.FindAll() how do you iterate through each of them and get the properties without creating a DirectoryEntry

I've tried the code snippet below but it's WAY slower than my original version ...
// Repeating this line for each property:
 
string emailAddress = resEnt.GetDirectoryEntry().Properties["Mail"].Value.ToString();
 
// is way slower than doing this for each object in mySearcher.FindAll():
 
DirectoryEntry de = resent.GetDirectoryEntry();
string emailAddress = de.Properties["Mail"].Value.ToString();
string givenName = de.Properties["givenName"].Value.ToString();

Open in new window


You're still getting the Directory Entry though, that's the bit that's slow :)

Instead, we can pull the values directly from resEnt (as below).

The properties loaded into the result can be explicitly set with:

mySearcher.PropertiesToLoad.Add("attributename");

Or:

mySearcher.PropertiesToLoad.AddRange(new String[] {"mail", "givenname"});

The idea being to reduce the cost of the search by returning only attributes we're interested in seeing.

Chris
string emailAddress = resEnt.Properties["mail"][0].ToString();
givenName = resEnt.Properties["givenname"][0].ToString();

Open in new window


Just noticed I missed the variable type for the second command, but I'm sure you'll catch that anyway :)

Chris
Avatar of atomicstorm
atomicstorm

ASKER

I did something completely different but your solution guided me in the right direction.
Very handy, thanks Chris.  It's nothing to do with what you wrote but it's interesting how the same code returns a different number of users from AD if converted to VB.NET ...

Really? It shouldn't make any difference if both are just using .NET classes, I normally test in both languages.

Chris
Yeah, it surprised me too.  C# returns 439 users in the AD I'm testing on but VB only returns 200 or so.

Hmmm I can't provide an answer for that, I've never noticed a difference when I've been testing things. At least not unless I go and make a mistake :)

Almost tempted to get you to try it in PowerShell as well, that can use the .NET framework as well :)

Chris
Hehe yep, it's probably something I've done but I haven't bothered trying to fix it yet.  PowerShell rocks!  I do a ton of it here at work although to be honest I'm battling with loading an external DLL into PowerShell through reflection at the moment lol