I have got a request from a client to fetch all client user details from AD and finally dump to a db so that they can use it for reporting.
I have used DirectoryEntry and PrincipalContext class to retrieve all the information.The user volume is approx 7500 and and for each user i am binding 35 AD attributes in a list of object.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.IO;
using AccountCheck;
using Microsoft.ActiveDirectory.Management.Commands;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.ComponentModel;
namespace testproj1
{
class Class1
{
//private static DateTime LonTS1;
//static void Main(string[] args)
// public static int LoadADUsers()
static void Main(string[] args)
{
int userCount = 0;
int maxPasswordAge = 90;
string LDAP_QUERY = "LDAP://DC=xyz,DC=com";
string LDAP_FILTER = "(&(objectClass=user)(objectCategory=person))";
//string LDAP_FILTER = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))";
DirectoryEntry objDirEntry = new DirectoryEntry(LDAP_QUERY);
string[] aryPropertiesToRetrieve =
{"sAMAccountName","Company","whenCreated","department","description","Enabled","displayName","distinguishedName","mail","employeeID","accountExpires", "extensionAttribute11", "extensionAttribute12",
"extensionAttribute13", "extensionAttribute14","extensionAttribute7", "extensionAttribute9","givenName" ,"Initials","title","location","sn","LastLogoff","LastLogon","manager","ChangePasswordAtLogon",
"physicalDeliveryOfficeName", "pwdLastSet","PasswordNeverExpires","PasswordNotRequired","nTSecurityDescriptor","ProtectedFromAccidentalDeletion","usercannotchangepassword","userAccountControl","userPrincipalName","lastlogontimestamp",
};
List<string> adPropertyList = new List<string>(aryPropertiesToRetrieve);
DirectorySearcher objSearch = new DirectorySearcher(objDirEntry, LDAP_FILTER, aryPropertiesToRetrieve);
objSearch.Asynchronous = true;
objSearch.PageSize = 500;
objSearch.SizeLimit = 1000;
objSearch.SearchScope = SearchScope.Subtree;
SearchResultCollection objResults = objSearch.FindAll();
User adUser = new User();
List<User> allUsers = new List<User>();
//NewADObjectParameterSet na = new NewADObjectParameterSet();
//string SQL = string.Empty;
int userAccountControl = 0;
DateTime accountExpiration = DateTime.Now;
//DateTime? accountExpiration;
DateTime passwordLastSet = DateTime.Now;
int daysUntilPasswordExpiration = 0;
DateTime passwordExpiration = DateTime.Now;
int daysUntilAccountExpiration = 0;
double passwordAge = 0;
DateTime? LLon=null;
string Mgr;
bool MCPANL;
string pfcd;
foreach (SearchResult result in objResults)
{
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, GetPropertyValue(result, "sAMAccountName").ToString());
//accountExpiration = (DateTime)GetPropertyValue_name(result, "accountExpires", "displayName", "sAMAccountName");
//accountExpiration = (DateTime)GetPropertyValue(result, "accountExpires");
accountExpiration = (DateTime)GetPropertyValue(result, "accountExpires");
//accountExpiration = user.AccountExpirationDate.HasValue ? (DateTime)user.AccountExpirationDate : (DateTime?)null;
daysUntilAccountExpiration = accountExpiration.Subtract(DateTime.Now).Days;
userAccountControl = (int)GetPropertyValue(result, "userAccountControl");
passwordLastSet = (DateTime)GetPropertyValue(result, "pwdLastSet");
pfcd = (string)GetPropertyValue(result, "ProtectedFromAccidentalDeletion");
if (passwordLastSet == null)
{ MCPANL = true; }
else { MCPANL = false; }
Mgr = GetPropertyValue(result, "manager").ToString();
if (Mgr == "" || Mgr == null)
{ Mgr = ""; }
else
{ Mgr = Mgr.Substring(3, Mgr.IndexOf(",") - 3); }
//LLoff = (string)GetPropertyValue(result, "LastLogoff");
// LLon = user.LastLogon.HasValue ? (DateTime)user.LastLogon : (DateTime?) null;
LLon = user.LastLogon;
if (userAccountControl > 10000) //password never expires
{
daysUntilPasswordExpiration = daysUntilAccountExpiration;
passwordExpiration = accountExpiration;
}
else
{
passwordAge = DateTime.Now.Subtract(passwordLastSet).TotalDays;
daysUntilPasswordExpiration = maxPasswordAge - (int)Math.Round(passwordAge + 1);
passwordExpiration = DateTime.Now.AddDays(daysUntilPasswordExpiration);
}
adUser = new User()
{
Name = GetPropertyValue(result, "sAMAccountName").ToString(),
Company = GetPropertyValue(result, "Company").ToString(),
Creation_Date = GetPropertyValue(result, "whenCreated").ToString(),
Department = GetPropertyValue(result, "department").ToString(),
Description = GetPropertyValue(result, "description").ToString(),
Enabled = user.Enabled,
Display_Name = GetPropertyValue(result, "displayName").ToString(),
Distinguished_Name = GetPropertyValue(result, "distinguishedName").ToString(),
Email = GetPropertyValue(result, "mail").ToString(),
EmployeeID = GetPropertyValue(result, "employeeID").ToString(),
Expiration_Date = accountExpiration,
extensionAttribute11 = GetPropertyValue(result, "extensionAttribute11").ToString(),
extensionAttribute12 = GetPropertyValue(result, "extensionAttribute12").ToString(),
extensionAttribute13_Room = GetPropertyValue(result, "extensionAttribute13").ToString(),
extensionAttribute14_Ext = GetPropertyValue(result, "extensionAttribute14").ToString(),
extensionAttribute7_IAM_ID = GetPropertyValue(result, "extensionAttribute7").ToString(),
extensionAttribute9_CostCenter = GetPropertyValue(result, "extensionAttribute9").ToString(),
First_Name = GetPropertyValue(result, "givenName").ToString(),
Initials = GetPropertyValue(result, "Initials").ToString(),
Job_Title = GetPropertyValue(result, "title").ToString(),
//Last_Known_Location = GetPropertyValue(result, "location").ToString(),
Last_Name = GetPropertyValue(result, "sn").ToString(),
// lastLogoff = new DateTime(1601, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(LLoff),
//lastLogoff=
lastLogon = LLon,
Manager = Mgr,
Must_Change_Password_At_Next_Logon = MCPANL,
Office = GetPropertyValue(result, "physicalDeliveryOfficeName").ToString(),
Password_Age_In_Days = passwordAge,
Password_Expiration_Date = passwordExpiration,
Password_Last_Changed = passwordLastSet,
Password_Never_Expire = user.PasswordNeverExpires,
Password_Not_Required = user.PasswordNotRequired,
physicalDeliveryOfficeName = GetPropertyValue(result, "physicalDeliveryOfficeName").ToString(),
//Protected_From_Accidental_Deletion = GetPropertyValue(result, "ProtectedFromAccidentalDeletion").ToString(),
User_Cannot_Change_Password = user.UserCannotChangePassword,
userAccountControl = GetPropertyValue(result, "userAccountControl").ToString(),
Username = GetPropertyValue(result, "userPrincipalName").ToString(),
Username_pre_2000 = GetPropertyValue(result, "sAMAccountName").ToString(),
//lastLogon_value= LLonTS1
};
allUsers.Add(adUser);
userCount++;
//Console.WriteLine("the count is" + userCount);
// Console.ReadLine();
} // end foreach SearchResult loop
string connectionstring = ConfigurationManager.ConnectionStrings["LDAP_ALLUSER"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionstring))
{
conn.Open();
string query = "truncate table [dbo].[adlook] ";
SqlCommand cmd1 = new SqlCommand(query, conn);
cmd1.ExecuteNonQuery();
SqlCommand cmd =
new SqlCommand(
"INSERT INTO [dbo].[ADlook] (name, company, creation_date,department,description,enabled,display_name,distinguished_name,email,employeeid,expiration_date,extensionattribute11,extensionattribute12,extensionattribute13_room,extensionattribute14_ext,extensionattribute7_iam_id,extensionattribute9_costcenter,first_name,initials,job_title,last_name,lastlogon,manager,must_change_password_at_next_logon,office,password_age_in_days,password_expiration_date,password_last_changed,password_never_expire,password_not_required,physicaldeliveryofficename,user_cannot_change_password,useraccountcontrol,username,username_pre_2000) " +
" VALUES (#name,#company,#creation_date,#department,#description,#enabled,#display_name,#distinguished_name,#email,#employeeid,#expiration_date,#extensionattribute11,#extensionattribute12,#extensionattribute13_room,#extensionattribute14_ext,#extensionattribute7_iam_id,#extensionattribute9_costcenter,#first_name,#initials,#job_title,#last_name,#lastlogon,#manager,#must_change_password_at_next_logon,#office,#password_age_in_days,#password_expiration_date,#password_last_changed,#password_never_expire,#password_not_required,#physicaldeliveryofficename,#user_cannot_change_password,#useraccountcontrol,#username,#username_pre_2000)");
cmd.CommandType = CommandType.Text;
cmd.Connection = conn;
cmd.Parameters.Add("#name",DbType.String); cmd.Parameters.Add("#company",DbType.String); cmd.Parameters.Add("#creation_date",DbType.DateTime); cmd.Parameters.Add("#department",DbType.String); cmd.Parameters.Add("#description",DbType.String); cmd.Parameters.Add("#enabled",DbType.Boolean);
cmd.Parameters.Add("#display_name",DbType.String); cmd.Parameters.Add("#distinguished_name",DbType.String); cmd.Parameters.Add("#email",DbType.String); cmd.Parameters.Add("#employeeid",DbType.String); cmd.Parameters.Add("#expiration_date",DbType.DateTime); cmd.Parameters.Add("#extensionattribute11",DbType.String);
cmd.Parameters.Add("#extensionattribute12",DbType.String); cmd.Parameters.Add("#extensionattribute13_room",DbType.String); cmd.Parameters.Add("#extensionattribute14_ext",DbType.String); cmd.Parameters.Add("#extensionattribute7_iam_id",DbType.String); cmd.Parameters.Add("#extensionattribute9_costcenter",DbType.String); cmd.Parameters.Add("#first_name",DbType.String);
cmd.Parameters.Add("#initials",DbType.String); cmd.Parameters.Add("#job_title",DbType.String); cmd.Parameters.Add("#last_name",DbType.String); cmd.Parameters.Add("#lastlogon",DbType.DateTime); cmd.Parameters.Add("#manager",DbType.String); cmd.Parameters.Add("#must_change_password_at_next_logon",DbType.Boolean);
cmd.Parameters.Add("#office",DbType.String); cmd.Parameters.Add("#password_age_in_days",DbType.Int32); cmd.Parameters.Add("#password_expiration_date",DbType.DateTime); cmd.Parameters.Add("#password_last_changed",DbType.DateTime); cmd.Parameters.Add("#password_never_expire",DbType.Boolean); cmd.Parameters.Add("#password_not_required",DbType.Boolean);
cmd.Parameters.Add("#physicaldeliveryofficename",DbType.String); cmd.Parameters.Add("#user_cannot_change_password",DbType.Boolean); cmd.Parameters.Add("#useraccountcontrol",DbType.String); cmd.Parameters.Add("#username",DbType.String); cmd.Parameters.Add("#username_pre_2000",DbType.String);
foreach (var item in allUsers)
{
cmd.Parameters[0].Value = item.Name; cmd.Parameters[1].Value = item.Company; cmd.Parameters[2].Value = item.Creation_Date; cmd.Parameters[3].Value = item.Department; cmd.Parameters[4].Value = item.Description;
cmd.Parameters[5].Value = item.Enabled; cmd.Parameters[6].Value = item.Display_Name; cmd.Parameters[7].Value = item.Distinguished_Name; cmd.Parameters[8].Value = item.Email; cmd.Parameters[9].Value = item.EmployeeID;
cmd.Parameters[10].Value = item.Expiration_Date; cmd.Parameters[11].Value = item.extensionAttribute11; cmd.Parameters[12].Value = item.extensionAttribute12; cmd.Parameters[13].Value = item.extensionAttribute13_Room; cmd.Parameters[14].Value = item.extensionAttribute14_Ext;
cmd.Parameters[15].Value = item.extensionAttribute7_IAM_ID; cmd.Parameters[16].Value = item.extensionAttribute9_CostCenter; cmd.Parameters[17].Value = item.First_Name; cmd.Parameters[18].Value = item.Initials; cmd.Parameters[19].Value = item.Job_Title;
cmd.Parameters[20].Value = item.Last_Name;cmd.Parameters[21].Value = (object)item.lastLogon ?? DBNull.Value;cmd.Parameters[22].Value = item.Manager; cmd.Parameters[23].Value = item.Must_Change_Password_At_Next_Logon; cmd.Parameters[24].Value = item.Office;
cmd.Parameters[25].Value = item.Password_Age_In_Days; cmd.Parameters[26].Value = item.Password_Expiration_Date; cmd.Parameters[27].Value = item.Password_Last_Changed; cmd.Parameters[28].Value = item.Password_Never_Expire; cmd.Parameters[29].Value = item.Password_Not_Required;
cmd.Parameters[30].Value = item.physicalDeliveryOfficeName; cmd.Parameters[31].Value = item.User_Cannot_Change_Password; cmd.Parameters[32].Value = item.userAccountControl; cmd.Parameters[33].Value = item.Username; cmd.Parameters[34].Value = item.Username_pre_2000;
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
///////////////////////////////////////// 1st method starts
private static object GetPropertyValue(SearchResult result, string propertyName)
{
object propValue = null;
if (result.Properties.Contains(propertyName))
{
if (result.Properties[propertyName].Count > 0)
{
propValue = result.Properties[propertyName][0];
if (propertyName == "accountExpires" || propertyName == "pwdLastSet")
{
long dateValue = (long)propValue;
long maxDate = DateTime.MaxValue.ToFileTime();
if (dateValue == 0 || dateValue > maxDate || dateValue == null) //never expires
{
propValue = Convert.ToDateTime("12/31/2100"); //new DateTime(2100, 12, 31);
}
else //expires
{
propValue = DateTime.FromFileTime(dateValue);
}
}
}
}
else
{
propValue = string.Empty;
}
return propValue;
}
////////////////////////////// 1st method ends
}
}
there are no errors as of now and it is just code that takes long to retrieve information.`
The code iterates each user and adds the to the object allUsers.
It takes approximately 13mins to add all users to this object which seems like a long time and will appreciate if someone can help me if i am doing anything wrong in coding part.
i have wrote a User class where all the property definitions are there and connection string to dump into db is being inherited from App.Config.
In the below code *****allUsers.Add(adUser)*****; is the part where it will add one by one user details and until it adds all users (almost 7500) , it takes at-least 14 mins of time.
Please help so that i can do any changes to code to make this process faster and i can add all user data in the object faster.
There is more than One way to Access LDAP Data and They perform diffrent in Diffrent enviorments. I use This Method and its pretty fast. May be you wanna give it a try.
var context = new PrincipalContext(ContextType.Domain, "yourdomainasaString");
var qbeUser = new UserPrincipal(context);
var searcher = new PrincipalSearcher(qbeUser);
foreach (DirectoryEntry de in searcher.FindAll().Select(x => x.GetUnderlyingObject()))
{
var tmpsid = de.Properties["objectSid"].Value;
var tmproles = de.Properties["memberof"].Value;
var IsActive = de.Properties["userAccountControl"][0].ToString() != "514";
//And So on
}
My GetActiveDirectory() method is used to get data from Active Directory using the SamAccountName, and it's working but the problem is the user.EmployeeId return no sign of data.
Why I can't receive the EmployeeId and how can I fix it?
This is my codes:
public void GetActiveDirectory(DataTable DataStorage, string SamAccountName)
{
var domainContext = new PrincipalContext(
ContextType.Domain, null, _ldapPath, _ldapUsername, _ldapPassword);
var group = GroupPrincipal.FindByIdentity(domainContext, "Domain Users");
if (group != null)
{
DataStorage.Columns.Add("SamAccountName");
DataStorage.Columns.Add("Surname");
DataStorage.Columns.Add("Guid");
DataStorage.Columns.Add("Enabled");
DataStorage.Columns.Add("GivenName");
DataStorage.Columns.Add("EmailAddress");
DataStorage.Columns.Add("SID");
DataStorage.Columns.Add("DateCreated");
DataStorage.Columns.Add("DateModified");
DataStorage.Columns.Add("EmployeeNumber");
DataStorage.AcceptChanges();
foreach (var p in group.GetMembers(false))
{
if(p.SamAccountName != null)
{
try
{
var user = UserPrincipal.FindByIdentity(
domainContext, IdentityType.SamAccountName, SamAccountName);
if (user != null)
{
var userDE = (DirectoryEntry)p.GetUnderlyingObject();
DateTime dateCreated = userDE.Properties["WhenCreated"].Value != null
? (DateTime)userDE.Properties["WhenCreated"].Value
: DateTime.MinValue;
DateTime dateModified = userDE.Properties["WhenChanged"].Value != null
? (DateTime)userDE.Properties["WhenChanged"].Value
: DateTime.MinValue;
DataRow dr = DataStorage.NewRow();
dr["SamAccountName"] = user.SamAccountName;
dr["Surname"] = user.Surname;
dr["Guid"] = user.Guid.ToString();
dr["Enabled"] = user.Enabled;
dr["GivenName"] = user.GivenName;
dr["EmailAddress"] = user.EmailAddress;
dr["SID"] = user.Sid.Value;
dr["EmployeeNumber"] = user.EmployeeId; //Always give an empty space or null.
dr["DateCreated"] = dateCreated;
dr["DateModified"] = dateModified;
DataStorage.Rows.Add(dr);
return;
}
}
catch { }
break;
}
}
}
}
THIS IS A TEMPORARY ANSWER TO UserPrincipal.EmployeeId
I don't know why UserPrincipal.EmployeeId is not working so I decide to use the old way method.
What I've tried to solve my own problem in .EmployeeId is to go back using System.DirectoryServices
Here is my method to get EmployeeId using System.DirectoryServices
var oDirecotyrEntry = new DirectoryEntry(
_ldapPath, _ldapUsername, _ldapPassword, AuthenticationTypes.Secure);
SearchResultCollection odrSearchResultCollection;
var odrUser = new DirectoryEntry();
var odrDirectorySearcher = new DirectorySearcher
{Filter = "sAMAccountName="+SamAccountName+"", SearchRoot = oDirecotyrEntry};
using(odrDirectorySearcher)
{
odrSearchResultCollection = odrDirectorySearcher.FindAll();
if(odrSearchResultCollection.Count > 0)
{
foreach(SearchResult result in odrSearchResultCollection)
{
var num = result.Properties["employeeNumber"];
foreach(var no in num)
{
dr["EmployeeNumber"] = no.ToString();
}
}
}
}
and to complete my project I use System.DirectoryServices.AccountManagement
var oPricipalContext = new PrincipalContext(
ContextType.Domain, _ldapPath2, _ldapUsername, _ldapPassword);
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPricipalContext, SamAccountName);
if (oUserPrincipal != null)
{
var oDateTime = (DirectoryEntry)oUserPrincipal.GetUnderlyingObject();
DateTime dateCreated = oDateTime.Properties["WhenCreated"].Value != null
? (DateTime)oDateTime.Properties["WhenCreated"].Value
: DateTime.MinValue;
DateTime dateChanged = oDateTime.Properties["WhenChanged"].Value != null
? (DateTime)oDateTime.Properties["WhenChanged"].Value
: DateTime.MinValue;
dr["SamAccountName"] = oUserPrincipal.SamAccountName;
dr["Surname"] = oUserPrincipal.Surname;
dr["Guid"] = oUserPrincipal.Guid.ToString();
dr["Enabled"] = oUserPrincipal.Enabled;
dr["GivenName"] = oUserPrincipal.GivenName;
dr["EmailAddress"] = oUserPrincipal.EmailAddress;
dr["SID"] = oUserPrincipal.Sid.Value;
dr["DateCreated"] = dateCreated;
dr["DateModified"] = dateChanged;
DataStorage.Rows.Add(dr);
}
System.DirectoryServices.AccountManagement is require to my project so I need to use it.
SORRY FOR MY GRAMMAR.
Here is my full code.
No snippet format???
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
public void GetUsers(DataTable DataStorage, string SamAccountName)
{
DataStorage.Columns.Add("SamAccountName");
DataStorage.Columns.Add("Surname");
DataStorage.Columns.Add("Guid");
DataStorage.Columns.Add("Enabled");
DataStorage.Columns.Add("GivenName");
DataStorage.Columns.Add("EmailAddress");
DataStorage.Columns.Add("SID");
DataStorage.Columns.Add("DateCreated");
DataStorage.Columns.Add("DateModified");
DataStorage.Columns.Add("EmployeeNumber");
DataStorage.AcceptChanges();
DataRow dr = DataStorage.NewRow();
//System.DirectoryServices
var oDirecotyrEntry = new DirectoryEntry(
_ldapPath, _ldapUsername, _ldapPassword, AuthenticationTypes.Secure);
SearchResultCollection odrSearchResultCollection;
var odrUser = new DirectoryEntry();
var odrDirectorySearcher = new DirectorySearcher
{Filter = "sAMAccountName="+SamAccountName+"", SearchRoot = oDirecotyrEntry};
using(odrDirectorySearcher)
{
odrSearchResultCollection = odrDirectorySearcher.FindAll();
if(odrSearchResultCollection.Count > 0)
{
foreach(SearchResult result in odrSearchResultCollection)
{
var num = result.Properties["employeeNumber"];
foreach(var no in num)
{
dr["EmployeeNumber"] = no.ToString();
}
}
}
}
//System.DirectoryServices.AccountManagement
var oPricipalContext = new PrincipalContext(
ContextType.Domain, _ldapPath2, _ldapUsername, _ldapPassword);
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPricipalContext, SamAccountName);
if (oUserPrincipal != null)
{
var oDateTime = (DirectoryEntry)oUserPrincipal.GetUnderlyingObject();
DateTime dateCreated = oDateTime.Properties["WhenCreated"].Value != null
? (DateTime)oDateTime.Properties["WhenCreated"].Value
: DateTime.MinValue;
DateTime dateChanged = oDateTime.Properties["WhenChanged"].Value != null
? (DateTime)oDateTime.Properties["WhenChanged"].Value
: DateTime.MinValue;
dr["SamAccountName"] = oUserPrincipal.SamAccountName;
dr["Surname"] = oUserPrincipal.Surname;
dr["Guid"] = oUserPrincipal.Guid.ToString();
dr["Enabled"] = oUserPrincipal.Enabled;
dr["GivenName"] = oUserPrincipal.GivenName;
dr["EmailAddress"] = oUserPrincipal.EmailAddress;
dr["SID"] = oUserPrincipal.Sid.Value;
dr["DateCreated"] = dateCreated;
dr["DateModified"] = dateChanged;
DataStorage.Rows.Add(dr);
}
}