SharePoint: Querying Active Directory using C#.Net

Introduction 

If you are developing a SharePoint solution and you are required to work with User Accounts, the User Profile Service has a wealth of information you can use. However, in some cases you may need to query Active Directory directly. This article focuses on using the System.DirectoryServices.AccountManagement namespace, new to the .Net Framework in version 3.5, to query Active Directory groups.

The System.DirectoryServices.AccountManagement namespace makes interacting with Active Directory very easy. To quote the Microsoft MSDN Documentation:

"Managed directory services applications can take advantage of the AccountManagement API to simplify management of user, computer and group principals. Solutions that previously required intricate knowledge of the store or lengthy code, such as finding all groups to which a user belongs, are accomplished in a few lines of code with the AccountManagement API."

A recent question in the SharePoint Development forum was asked about retrieving the users from an Active Directory group, How to get the users from active directory group using C#?, and this article demonstrates how this can be achieved.

Simple Example

So, lets have a look at just how easy this is.

As basic example of using the System.DirectoryServices.AccountManagement namespace to (recursively), list all the users in the "Marketing" Active Directory group, in the Active Directory domain, easyas.com:

[Note]: Unless you are using Kerberos  authentication in your SharePoint environment, you will need to pass a valid user and user password combination to the constructor of the PrincipalContext object. This username/password combination will be used to authenticate with Active Directory, and will need to have the appropriate permissions to perform any of the actions you invoke (e.g. querying groups, adding members to groups, removing members from groups).

Username and password credentials can be stored in the SharePoint Secure Store. For more information about storing and retrieving credentials from the SharePoint Secure Store, see the following article: SharePoint: Retrieving Credentials from the Secure Store Application using C#

Create the PrincipalContext object that will be used to connect to Active Directory:

var principalContext = new  PrincipalContext(ContextType.Domain, "easyas.com", "fred",  "fredsPassword");

Find the group using the groups name:

GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, groupName);

That's it! Well, nearly. You've got the Active Directory group in two lines of code. Next you need to loop through the group's members looking for all the user accounts (UserPrincipals), and create a list of the names of users who belong to the group (in this example, we only want to list users who are members, not other groups or computers). For this part, loop through the members collection, adding each UserPrincipal object found to an ArrayList.

var members = groupPrincipal.GetMembers(true);
var membersList = new  ArrayList();
foreach (Principal member in members)
{
    UserPrincipal userPrincipal = member as  UserPrincipal;
    if (userPrincipal == null) continue;
    if (!membersList.Contains(userPrincipal.DisplayName))
    {
        membersList.Add(userPrincipal.DisplayName);
    }
}

Finally, format the results as HTML output.

var output = new  StringBuilder();
output.AppendLine(String.Format("<span>Users in the {0} group:</span><br/>", groupName));
output.AppendLine("<ul>");
foreach (string s in membersList)
{
    output.AppendLine(String.Format("<li>{0}</li>", s));
}
output.AppendLine("</ul>");

The whole function looks like this:

private String GetMarketingUsersAsHtmlList()
{
    const string  adDomainName = "easyas.com";
    const string  adUserAccount = "fred";
    const string  adUserAccountPassword = "HokeyPokey";
    var principalContext = new  PrincipalContext(ContextType.Domain, adDomainName, adUserAccount, adUserAccountPassword);
    const string  groupName = "Marketing";
     
    GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, groupName);
    if (groupPrincipal == null)
    {
        return String.Empty;
    }
 
    try
    {
        var members = groupPrincipal.GetMembers(true);
        var membersList = new  ArrayList();
        foreach (Principal member in members)
        {
            UserPrincipal userPrincipal = member as  UserPrincipal;
            if (userPrincipal == null) continue;
            if (!membersList.Contains(userPrincipal.DisplayName))
            {
                membersList.Add(userPrincipal.DisplayName);
            }
        }
 
        var output = new  StringBuilder();
        output.AppendLine(String.Format("<span>Users in the {0} group:</span><br/>", groupName));
        output.AppendLine("<ul>");
        foreach (string s in membersList)
        {
            output.AppendLine(String.Format("<li>{0}</li>", s));
        }
        output.AppendLine("</ul>");
        return output.ToString();
    }
    finally
    {
        groupPrincipal.Dispose();
    }
}

Webpart Example One

 
An example of querying an Active Directory group, Developers, using the SID of the current use session (SPContext.Current.Web.CurrentUser.Sid). The following code snippet shows how to use the System.DirectoryServices.AccountManagement namespace in a standard SharePoint Webpart.

using System;
using System.ComponentModel;
using System.DirectoryServices.AccountManagement;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
 
namespace SharePointTesting.IsUserAMember
{
    [ToolboxItemAttribute(false)]
    public class  IsUserAMember : WebPart
    {
        private Label _results;
 
 
        private static  PrincipalContext GetPrincipalContext
        {
            get
            {
                const string  adDomainName = "easyas.com";
                const string  adUserAccount = "svcAdQueryAccount";
                const string  adUserAccountPassword = "svcAdQueryAccountPassword";
                var principalContext = new  PrincipalContext(ContextType.Domain, adDomainName, adUserAccount, adUserAccountPassword);
                return principalContext;
            }
        }
 
        private Boolean IsUserMemberOfGroup(GroupPrincipal groupPrincipal, String identity, IdentityType identityType)
        {
            UserPrincipal userPrincipal = GetUser(identity, identityType);
            if (userPrincipal == null) return  false;
            return userPrincipal.IsMemberOf(groupPrincipal);
        }
 
        private UserPrincipal GetUser(String identity, IdentityType identityType)
        {
            PrincipalContext principalContext = GetPrincipalContext;
            return UserPrincipal.FindByIdentity(principalContext, identityType, identity);
        }
 
        private GroupPrincipal GetGroup(String groupName)
        {
            PrincipalContext principalContext = GetPrincipalContext;
            return GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName);
        }
 
        protected override  void OnInit(EventArgs e)
        {
            base.OnInit(e);
            _results = new  Label();
        }
 
        protected override  void CreateChildControls()
        {
            Controls.Add(_results);
        }
 
        protected override  void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            StringBuilder output = new  StringBuilder();
            GroupPrincipal group = GetGroup("Developers");
            if (group == null)
            {
                _results.Text = "Group not found.";
                return;
            }
            output.Append(String.Format("Current user, {0}, {1} a member of {2}", SPContext.Current.Web.CurrentUser.Name, IsUserMemberOfGroup(group, SPContext.Current.Web.CurrentUser.Sid, IdentityType.Sid) ? "is" :  "is not", group.DisplayName));
            output.Append("<br/>");
            _results.Text = output.ToString();
        }
    }
}

Webpart Example Two

 
An example of recursively querying an Active Directory group, Developers, and displaying all of the groups members. The following code snippet shows how to use the System.DirectoryServices.AccountManagement namespace in a standard SharePoint Webpart.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.DirectoryServices.AccountManagement;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
 
namespace SharePointTesting.GetMembersInGroup
{
    [ToolboxItemAttribute(false)]
    public class  GetMembersInGroup : WebPart
    {
        private Label _results;
 
 
        private static  PrincipalContext GetPrincipalContext
        {
            get
            {
                const string  adDomainName = "easyas.com";
                const string  adUserAccount = "svcAdQueryAccount";
                const string  adUserAccountPassword = "svcAdQueryAccountPassword";
                var principalContext = new  PrincipalContext(ContextType.Domain, adDomainName, adUserAccount, adUserAccountPassword);
                return principalContext;
            }
        }
 
        private Boolean IsUserMemberOfGroup(GroupPrincipal groupPrincipal, String identity, IdentityType identityType)
        {
            UserPrincipal userPrincipal = GetUser(identity, identityType);
            if (userPrincipal == null) return  false;
            return userPrincipal.IsMemberOf(groupPrincipal);
        }
 
        private UserPrincipal GetUser(String identity, IdentityType identityType)
        {
            PrincipalContext principalContext = GetPrincipalContext;
            return UserPrincipal.FindByIdentity(principalContext, identityType, identity);
        }
 
        private GroupPrincipal GetGroup(String groupName)
        {
            PrincipalContext principalContext = GetPrincipalContext;
            return GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName);
        }
 
        private List<UserPrincipal> GetAllUsersInGroup(GroupPrincipal groupPrincipal, Boolean recurse)
        {
            List<UserPrincipal> userPrincipals = new  List<UserPrincipal>();
            PrincipalSearchResult<Principal> members = groupPrincipal.GetMembers(recurse);
            foreach (Principal principal in members)
            {
                var userPrincipal = principal as  UserPrincipal;
                if (userPrincipal == null) continue;
                userPrincipals.Add(userPrincipal);
            }
            return userPrincipals;
        }
 
        protected override  void OnInit(EventArgs e)
        {
            base.OnInit(e);
            _results = new  Label();
        }
 
        protected override  void CreateChildControls()
        {
            Controls.Add(_results);
        }
 
        protected override  void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            StringBuilder output = new  StringBuilder();
            GroupPrincipal group = GetGroup("Developers");
            if (group == null)
            {
                _results.Text = "Group not found.";
                return;
            }
            var groupMembers = GetAllUsersInGroup(group, true);
            String members = String.Empty;
            foreach (UserPrincipal userPrincipal in groupMembers)
            {
                members = String.Format("{0}{1}", String.IsNullOrEmpty(members) ? "" : String.Format("{0}, ", members), userPrincipal.DisplayName);
            }
            output.Append(String.Format("Current user, {0}, {1} a member of {2}", SPContext.Current.Web.CurrentUser.Name, IsUserMemberOfGroup(group, SPContext.Current.Web.CurrentUser.Sid, IdentityType.Sid) ? "is" :  "is not", group.DisplayName));
            output.Append("<br/><br/>");
            output.Append(String.Format("The current list of users in the {0} group are: {1}", group.DisplayName, members));
            _results.Text = output.ToString();
        }
    }
}

Other Examples

The list of functions below demonstrates how easy it is to create a number of helper functions that can be used in a SharePoint solution for interacting with Active Directory. All of the examples use the following property to get the PrincipalContext, and some of the examples reference other methods in this section. 

Get the PrincipalContext

private static  PrincipalContext GetPrincipalContext
{
    get
    {
        const string  adDomainName = "easyas.com";
        const string  adUserAccount = "svcAdQueryAccount";
        const string  adUserAccountPassword = "svcAdQueryAccountPassword";
        var principalContext = new  PrincipalContext(ContextType.Domain, adDomainName, adUserAccount, adUserAccountPassword);
        return principalContext;
    }
}

Get a Group

private GroupPrincipal GetGroup(String groupName)
{
    PrincipalContext principalContext = GetPrincipalContext;
    return GroupPrincipal.FindByIdentity(principalContext, IdentityType.Name, groupName);
}

Get a User

private UserPrincipal GetUser(String samAccountName)
{
    PrincipalContext principalContext = GetPrincipalContext;
    return UserPrincipal.FindByIdentity(principalContext, IdentityType.SamAccountName, samAccountName);
}
 
private UserPrincipal GetUser(String identity, IdentityType identityType)
{
    PrincipalContext principalContext = GetPrincipalContext;
    return UserPrincipal.FindByIdentity(principalContext, identityType, identity);
}

Check if a User is a Member of a Group

private Boolean IsUserMemberOfGroup(GroupPrincipal groupPrincipal, String samAccountName)
{
    UserPrincipal userPrincipal = GetUser(samAccountName);
    if (userPrincipal == null) return  false;
    return userPrincipal.IsMemberOf(groupPrincipal);
}
 
private Boolean IsUserMemberOfGroup(GroupPrincipal groupPrincipal, String identity, IdentityType identityType)
{
    UserPrincipal userPrincipal = GetUser(identity, identityType);
    if (userPrincipal == null) return  false;
    return userPrincipal.IsMemberOf(groupPrincipal);
}
 
private Boolean IsUserMemberOfGroup(GroupPrincipal groupPrincipal, UserPrincipal userPrincipal)
{
    return userPrincipal.IsMemberOf(groupPrincipal);
}

Get a List of all the Users in a Group

private List<UserPrincipal> GetAllUsersInGroup(GroupPrincipal groupPrincipal, Boolean recurse)
{
    List<UserPrincipal> userPrincipals = new  List<UserPrincipal>();
    PrincipalSearchResult<Principal> members = groupPrincipal.GetMembers(recurse);
    foreach (Principal principal in members)
    {
        var userPrincipal = principal as  UserPrincipal;
        if (userPrincipal == null) continue;
        userPrincipals.Add(userPrincipal);
    }
    return userPrincipals;
}

Add or Remove a User from a Group

private void  AddUserToGroup(GroupPrincipal groupPrincipal, String samAccountName)
{
    UserPrincipal userPrincipal = GetUser(samAccountName);
    if (userPrincipal == null) throw  new NullReferenceException("The user does not exist.");
    AddUserToGroup(groupPrincipal,userPrincipal)
    userPrincipal.Dispose();
}
 
private void  AddUserToGroup(GroupPrincipal groupPrincipal, UserPrincipal userPrincipal)
{   
    if (!userPrincipal.IsMemberOf(groupPrincipal))
    {
        groupPrincipal.Members.Add(userPrincipal);
        groupPrincipal.Save();
    }
}
 
private void  RemoveUserFromGroup(GroupPrincipal groupPrincipal, String samAccountName)
{
    UserPrincipal userPrincipal = GetUser(samAccountName);
    if (userPrincipal == null) throw  new NullReferenceException("The user does not exist.");
    RemoveUserFromGroup(groupPrincipal,userPrincipal)
    userPrincipal.Dispose();
}
 
private void  RemoveUserFromGroup(GroupPrincipal groupPrincipal, UserPrincipal userPrincipal)
{   
    if (userPrincipal.IsMemberOf(groupPrincipal))
    {
        groupPrincipal.Members.Remove(userPrincipal);
        groupPrincipal.Save();
    }   
}

See Also