Description
This C# code will run every X minutes (15) and do the following:
-Find a list of users in a specified security/distribution group in ADUC (and any groups nested within that group)
-For each entry in the list, collect a list of properties from their ADUC object
-(If the entry is setup in Exchange to forward to a different email address, it will use the address it is being forwarded to)
-Add the list of entries to a SharePoint list. (If an entry with a specific GUID already exists in the list, then it will just update that entry rather than adding a new one)
-Remove any entries from the list that haven’t been updated in 1 day.
==NOTE==
- This code is in TWO files. Don’t just copy and paste it into one. For full instructions on how to create the Timer Job, please see the link below in the Credits section.
- The Microsoft.Sharepoint references are only available on a SharePoint server. Therefore, you must compile this from Visual Studio installed on a SharePoint server.
==CREDITS==
Linking SharePoint to ActiveDirectory User:
Create a SharePoint Timer Job:
Nested AD Groups:
http://www.codeproject.com/Articles/27281/Retrieve-Names-from-Nested-AD-Groups
Source Code
==TIMER JOB FILE==
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
namespace ActiveDirectoryList
{
public class ActiveDirectoryTimerJob : SPJobDefinition
{
public const string JOB_NAME = "ActiveDirectoryTimerJob";
public ActiveDirectoryTimerJob() : base() { }
public ActiveDirectoryTimerJob(SPWebApplication webApp)
: base(JOB_NAME, webApp, null, SPJobLockType.Job)
{
this.Title = JOB_NAME;
}
public class NullHandler
{
public static string GetString(object value)
{
return (value == null || value == DBNull.Value) ? string.Empty : value.ToString();
}
}
public class LdapUser
{
public int ID { get; set; }
public bool IsActive { get; set; }
public string GUID { get; set; }
public string displayName { get; set; }
public string givenName { get; set; }
public string sn { get; set; }
public string title { get; set; }
public string description { get; set; }
public string company { get; set; }
public string streetAddress { get; set; }
public string l { get; set; }
public string st { get; set; }
public string postalCode { get; set; }
public string homePhone { get; set; }
public string telephoneNumber { get; set; }
public string ipPhone { get; set; }
public string mobile { get; set; }
public string facsimileTelephoneNumber { get; set; }
public string wWWHomePage { get; set; }
public string mail { get; set; }
}
static Hashtable searchedGroups = null;
public static List<LdapUser> getGroupMembers(string strGroupName)
{
var groupMembers = new List<LdapUser>();
searchedGroups = new Hashtable();
// find group
DirectorySearcher search = new DirectorySearcher("LDAP://DC=YourDomain,DC=com");
search.Filter = String.Format
("(&(objectCategory=group)(cn={0}))", strGroupName);
search.PropertiesToLoad.Add("distinguishedName");
SearchResult sru = null;
DirectoryEntry group;
try
{
sru = search.FindOne();
}
catch (Exception ex)
{
throw ex;
}
group = sru.GetDirectoryEntry();
groupMembers = getUsersInGroup(group.Properties["distinguishedName"].Value.ToString());
return groupMembers;
}
private static List<LdapUser> getUsersInGroup(string strGroupDN)
{
var groupMembers = new List<LdapUser>();
searchedGroups.Add(strGroupDN, strGroupDN);
//const int UF_ACCOUNTDISABLE = 0x0002;
// find all users in this group
DirectorySearcher ds = new DirectorySearcher("LDAP://DC=YourDomain,DC=com");
ds.Filter = String.Format
("(&(memberOf={0})(objectClass=person))", strGroupDN);
var propertiesToLoad = new[]
{
"displayName",
"givenName",
"sn",
"title",
"description",
"company",
"streetAddress",
"l",
"st",
"postalCode",
"homePhone",
"telephoneNumber",
"ipPhone",
"mobile",
"facsimileTelephoneNumber",
"wWWHomePage",
"mail",
"deliverAndRedirect",
"altRecipient",
"userAccountControl",
"objectGUID",
"distinguishedName"
};
ds.PropertiesToLoad.AddRange(propertiesToLoad);
foreach (SearchResult sr in ds.FindAll())
{
var userEntry = sr.GetDirectoryEntry();
var ldapUser = new LdapUser();
ldapUser.displayName = NullHandler.GetString(userEntry.Properties["displayName"].Value);
if (string.IsNullOrEmpty(ldapUser.displayName))
continue;
ldapUser.givenName = NullHandler.GetString(userEntry.Properties["givenName"].Value);
ldapUser.sn = NullHandler.GetString(userEntry.Properties["sn"].Value);
ldapUser.title = NullHandler.GetString(userEntry.Properties["title"].Value);
ldapUser.description = NullHandler.GetString(userEntry.Properties["description"].Value);
ldapUser.company = NullHandler.GetString(userEntry.Properties["company"].Value);
ldapUser.streetAddress = NullHandler.GetString(userEntry.Properties["streetAddress"].Value);
ldapUser.l = NullHandler.GetString(userEntry.Properties["l"].Value);
ldapUser.st = NullHandler.GetString(userEntry.Properties["st"].Value);
ldapUser.postalCode = NullHandler.GetString(userEntry.Properties["postalCode"].Value);
ldapUser.homePhone = NullHandler.GetString(userEntry.Properties["homePhone"].Value);
ldapUser.telephoneNumber = NullHandler.GetString(userEntry.Properties["telephoneNumber"].Value);
ldapUser.ipPhone = NullHandler.GetString(userEntry.Properties["ipPhone"].Value);
ldapUser.mobile = NullHandler.GetString(userEntry.Properties["mobile"].Value);
ldapUser.facsimileTelephoneNumber = NullHandler.GetString(userEntry.Properties["facsimileTelephoneNumber"].Value);
ldapUser.wWWHomePage = NullHandler.GetString(userEntry.Properties["wWWHomePage"].Value);
if (
NullHandler.GetString(userEntry.Properties["altRecipient"].Value).Length > 0 &&
NullHandler.GetString(userEntry.Properties["deliverAndRedirect"].Value) != "True"
)
{
string forwardFQDN = "LDAP://" + NullHandler.GetString(userEntry.Properties["altRecipient"].Value);
using (DirectoryEntry forwardEntry = new DirectoryEntry(forwardFQDN))
{
ldapUser.mail = NullHandler.GetString(forwardEntry.Properties["mail"].Value);
}
}
else
{
ldapUser.mail = NullHandler.GetString(userEntry.Properties["mail"].Value);
}
//var userAccountControl = (int)userEntry.Properties["userAccountControl"].Value;
//ldapUser.IsActive = (userAccountControl & UF_ACCOUNTDISABLE) != UF_ACCOUNTDISABLE;
var guid = new Guid((byte[])userEntry.Properties["objectGUID"][0]);
ldapUser.GUID = guid.ToString("D");
groupMembers.Add(ldapUser);
}
// get nested groups
ArrayList al = getNestedGroups(strGroupDN);
foreach (object g in al)
{
// only if we haven't searched this group before - avoid endless loops
if (!searchedGroups.ContainsKey(g))
{
// get members in nested group
List<LdapUser> ml = getUsersInGroup(g as string);
// add them to result list
foreach (LdapUser s in ml)
{
groupMembers.Add(s);
}
}
}
return groupMembers;
}
private static ArrayList getNestedGroups(string strGroupDN)
{
ArrayList groupMembers = new ArrayList();
// find all nested groups in this group
DirectorySearcher ds = new DirectorySearcher("LDAP://DC=YourDomain,DC=com");
ds.Filter = String.Format
("(&(memberOf={0})(objectClass=group))", strGroupDN);
ds.PropertiesToLoad.Add("distinguishedName");
foreach (SearchResult sr in ds.FindAll())
{
groupMembers.Add(sr.Properties["distinguishedName"][0].ToString());
}
return groupMembers;
}
public void SaveActiveDirectoryUsersToSharePointList(IList<LdapUser> ldapUsers)
{
using (SPSite oSPSite = new SPSite("http://dcsharepoint"))
{
using (SPWeb oSPWeb = oSPSite.AllWebs["directory"])
{
string query = @"<Where><Eq><FieldRef Name='GUID0'/><Value Type='Text'>{0}</Value></Eq></Where>";
var ldapUserList = oSPWeb.Lists["Staff Directory"];
foreach (var ldapUser in ldapUsers)
{
SPQuery spQuery = new SPQuery();
spQuery.Query = string.Format(query, ldapUser.GUID);
var items = ldapUserList.GetItems(spQuery);
SPListItem listItem;
//if the user exists with the same guid then update
//otherwise create a new list item.
if (items.Count >= 1)
{
listItem = items[0];
}
else
{
listItem = ldapUserList.AddItem();
}
listItem["GUID0"] = ldapUser.GUID;
listItem["Name"] = ldapUser.displayName;
listItem["First_x0020_Name"] = ldapUser.givenName;
listItem["Last_x0020_Name"] = ldapUser.sn;
listItem["Designations"] = ldapUser.description;
listItem["Job_x0020_Title"] = ldapUser.title;
listItem["Company"] = ldapUser.company;
listItem["Street_x0020_Address"] = ldapUser.streetAddress;
listItem["City"] = ldapUser.l;
listItem["State"] = ldapUser.st;
listItem["Zip"] = ldapUser.postalCode;
listItem["Office_x0020_Main_x0020_Phone_x0"] = ldapUser.homePhone;
listItem["Extension"] = ldapUser.telephoneNumber;
listItem["Direct_x0020_Number"] = ldapUser.ipPhone;
listItem["Cell_x0020_Number"] = ldapUser.mobile;
listItem["Fax_x0020_Number"] = ldapUser.facsimileTelephoneNumber;
listItem["Website"] = ldapUser.wWWHomePage;
listItem["Email_x0020_Address"] = ldapUser.mail;
listItem.Update();
}
// if items in the list haven't been modified since yesterday, then delete them.
SPQuery deletedItemsQuery = new SPQuery();
deletedItemsQuery.Query = "<Where><Eq><FieldRef Name='Modified' /><Value Type='DateTime' IncludeTimeValue='FALSE'><Today OffsetDays='-1' /></Value></Eq></Where>";
SPListItemCollection deletedItems = ldapUserList.GetItems(deletedItemsQuery);
if (deletedItems.Count > 0)
{
for (int i = deletedItems.Count - 1; i >= 0; i--)
{
SPListItem item = deletedItems[i];
item.Delete();
}
}
}
}
}
public override void Execute(Guid targetInstanceId)
{
// Put your job's code here.
SaveActiveDirectoryUsersToSharePointList(getGroupMembers("Group-To-Search"));
}
}
}
==EVENT RECEIVER FILE==
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
namespace ActiveDirectoryList.Features.ProcessJobRequests
{
[Guid("VisualStudioWillGenerateAGUIDHere")]
public class ProcessJobRequestsEventReceiver : SPFeatureReceiver
{
const string JOB_NAME = "ActiveDirectoryTimerJob";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
// create the timer job when the feature is activated
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication; // get the web application reference
// Delete the job, If its already created
foreach (SPJobDefinition job in webApp.JobDefinitions)
if (job.Name == JOB_NAME)
{
job.Delete();
}
//Create the timer job by creating the instance of the class we have created
ActiveDirectoryTimerJob customTimerJob = new ActiveDirectoryTimerJob(webApp);
// Create a schedule interval for timer job
SPMinuteSchedule customSchedule = new SPMinuteSchedule(); // You can create Hourly, Daily, Weekly schedules as well
customSchedule.BeginSecond = 0;
customSchedule.EndSecond = 59;
customSchedule.Interval = 15; //Run every 15 minutes
// assign the schedule to the timer job
customTimerJob.Schedule = customSchedule;
customTimerJob.Update();
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
foreach (SPJobDefinition job in webApp.JobDefinitions)
{
if (job.Name == JOB_NAME)
{
job.Delete();
}
}
}
}
}