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();
}
}