Привязка пользовательских данных из AD с использованием LDAP (в c #) занимает около 13 минут для 7500 записей. Требуются советы по коду для повышения производительности - PullRequest
0 голосов
/ 24 мая 2019

Я получил запрос от клиента на получение всех пользовательских данных клиента из AD и, наконец, дамп на БД, чтобы они могли использовать его для отчетов.Я использовал классы DirectoryEntry и PrincipalContext для получения всей информации. Объем пользователя составляет около 7500, и для каждого пользователя я связываю 35 атрибутов AD в списке объектов.

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
    }

}

ошибок нетна данный момент, и это просто код, который занимает много времени для извлечения информации. Код выполняет итерацию каждого пользователя и добавляет к объекту allUsers.
Требуется около 13 минут, чтобы добавить всех пользователей к этому объекту, что кажется долгим временем и будетСпасибо, если кто-то может мне помочь, если я делаю что-то не так в части кодирования.

Я написал класс User, в котором есть все определения свойств и строка соединения для выгрузки в db наследуется от App.Config.

В приведенном ниже коде ***** allUsers.Add (adUser) *****;это та часть, где он добавляет по одному пользовательские данные, и пока он не добавит всех пользователей (почти 7500), это займет как минимум 14 минут времени.

Помогите, пожалуйста, чтобы я мог вносить любые изменения в код, чтобы ускорить этот процесс и быстрее добавлять все пользовательские данные в объект.

1 Ответ

0 голосов
/ 24 мая 2019

Существует несколько способов доступа к данным LDAP, и они работают по-разному в различных средах. Я использую этот метод, и он довольно быстрый. Может быть, вы хотите попробовать.

  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
}
...