AD поиски и свойства и использование - PullRequest
1 голос
/ 04 декабря 2011

Чтобы определить, являются ли учетные записи компьютеров осиротевшими, я хотел бы запросить все контроллеры домена всех доверенных доменов, чтобы получить lastLogon и lastLogonTimeStamp для всех компьютеров.У меня есть программа, которая работает (по крайней мере, в моей тестовой среде), но у меня есть несколько вопросов, на которые, я надеюсь, вы сможете ответить.

  1. Методы, которые я используюиспользовать, чтобы найти домены и контроллеры доменов, а затем извлечь информацию AD, используя как можно меньше ресурсов (ЦП и ОЗУ контроллера сети / контроллера домена)?Как их можно улучшить?

  2. Можно ли иметь более 1 значения в паре словарь ключ / значение?Наличие словаря для LastLogIn и другого для LastLogInTimestamp кажется бесполезным.

  3. Ссылка на словарь и свойства AD: как проверить несуществующие значения в отличие от использования Try/ Catch?

    try {// Этот DC больше тока, чем последний?if (dict_LastLogIn [pc] <(long) result.Properties ["lastlogon"] [0]) {dict_LastLogIn [pc] = (long) result.Properties ["lastlogon"] [0];}} catch {// Элемент еще не существует .. try {dict_LastLogIn [pc] = (long) result.Properties ["lastlogon"] [0];} catch {// .. или // Нет последнего LastLogin ... dict_LastLogIn [pc] = 0;}} </p>

Вот весь код:

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;


namespace dictionary
{
    class Program
    {
        internal static Dictionary<string, long> dict_LastLogIn =
            new Dictionary<string, long>();
        internal static Dictionary<string, long> dict_LastLogInTimeStamp =
            new Dictionary<string, long>();
        internal static Dictionary<string, DateTime> output =
            new Dictionary<string, DateTime>();

        internal static bool AreAllDCsResponding = true;

        static void Main(string[] args)
        {
            Console.BufferWidth = 150;
            Console.BufferHeight = 9999;
            Console.WindowWidth = 150;

            Dictionary<String, int> dict_domainList = new Dictionary<String, int>();
            Dictionary<String, int> dict_dcList = new Dictionary<String, int>();

            //Get the current domain's trusts.
            Domain currentDomain = Domain.GetCurrentDomain();
            Console.WriteLine("Retrieved the current Domain as {0}", currentDomain.ToString());
            var domainTrusts = currentDomain.GetAllTrustRelationships();
            Console.WriteLine("  {0} trusts were found.", domainTrusts.Count);
            //Add the current domain to the dictonary.  It won't be in domainTrusts!
            dict_domainList.Add(currentDomain.ToString(), 0);
            // Then add the other domains to the dictonary...
            foreach (TrustRelationshipInformation trust in domainTrusts)
            {
                dict_domainList.Add(trust.TargetName.Substring(0, trust.TargetName.IndexOf(".")).ToUpper(), 0);
                Console.WriteLine("    Adding {0} to the list of trusts.", trust.TargetName.Substring(0, trust.TargetName.IndexOf(".")).ToUpper());
            }
            // Now get all DCs per domain
            foreach (var pair in dict_domainList)
            {
                DirectoryContext dc = new DirectoryContext(DirectoryContextType.Domain, pair.Key);
                Domain _Domain = Domain.GetDomain(dc);
                foreach (DomainController Server in _Domain.DomainControllers)
                {
                    dict_dcList.Add(Server.Name, 0);
                    Console.WriteLine("      Adding {0} to the list of DCs.", Server.Name.ToUpper());

                }
                // Now search through every DC
                foreach (var _pair in dict_dcList)
                {
                    Console.WriteLine("        Querying {0} for Computer objects.", _pair.Key.ToUpper());
                    Search(pair.Key);
                    Console.WriteLine("\n");
                    Console.WriteLine("The following Computer objects were found:");
                }

                if (AreAllDCsResponding == true)
                {
                    ConvertTimeStamp(dict_LastLogIn);
                }
                else
                {
                    ConvertTimeStamp(dict_LastLogInTimeStamp);
                }
                Console.ReadLine();
            }
        }

        internal static void Search(string domainName)
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainName);
            DirectorySearcher mySearcher = new DirectorySearcher(entry);
            mySearcher.Filter = ("(&(ObjectCategory=computer))");//(lastlogon=*)(lastlogonTimeStamp=*))");
            mySearcher.SizeLimit = int.MaxValue;
            mySearcher.PropertiesToLoad.Add("DistinguishedName");
            mySearcher.PropertiesToLoad.Add("lastlogon");
            mySearcher.PropertiesToLoad.Add("lastlogonTimeStamp");
            try
            {
                foreach (System.DirectoryServices.SearchResult result in mySearcher.FindAll())
                {
                    string pc = result.Properties["DistinguishedName"][0].ToString();
                    try
                    {   // Is this DC more current than the last?
                        if (dict_LastLogIn[pc] < (long)result.Properties["lastlogon"][0])
                        {
                            dict_LastLogIn[pc] = (long)result.Properties["lastlogon"][0];
                        }
                    }
                    catch
                    {   // The item doesn't exist yet..
                        try
                        {
                            dict_LastLogIn[pc] = (long)result.Properties["lastlogon"][0];
                        }
                        catch
                        {   // .. or
                            // There is no last LastLogin...
                            dict_LastLogIn[pc] = 0;
                        }
                    }

                    try
                    {
                        // Not yet replicated?...
                        if (dict_LastLogInTimeStamp[pc] < (long)result.Properties["lastlogonTimeStamp"][0])
                        {
                            dict_LastLogInTimeStamp[pc] = (long)result.Properties["lastlogonTimeStamp"][0];
                        }
                    }
                    catch
                    {   // The item doesn't exist yet..
                        try
                        {
                            dict_LastLogInTimeStamp[pc] = (long)result.Properties["lastlogonTimeStamp"][0];
                        }
                        catch
                        {   // .. or
                            // There is no last LastLoginTimeStamp...
                            dict_LastLogInTimeStamp[pc] = 0;
                        }
                    }
                }
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                //If even one DC doesn't answer, don't use LastLogon!  
                //Use the less accurate, but replicated(!) LastLogonTimeStamp. 
                AreAllDCsResponding = false;
            }
        }

        internal static void ConvertTimeStamp(Dictionary<string, long> _dict)
        {
            foreach (var pair in _dict)
            {
                output.Add(pair.Key, DateTime.FromFileTime(pair.Value));
                Console.WriteLine("{0} - {1}", pair.Key, DateTime.FromFileTime(pair.Value));
            }
        }
    }
}

Спасибо за любую помощь, которую вы можете предложить.

1 Ответ

0 голосов
/ 04 декабря 2011

На высоком уровне, я не уверен, какова ваша конечная игра с этим, но вы уверены, что действительно хотите запросить каждый DC для lastLogon?Это может быть действительно дорого.Кроме того, почему вы ходите трестами?Вы уверены, что вам не нужны все домены в данном лесу (Forest.Domains)?

В ответ на ваши вопросы:

  1. Все выглядит нормальнов противном случае вы должны сделать несколько вещей:

    • Настройте фильтр на (&(objectCategory=computer)(objectClass=computer))
    • Добавить mySearcher.PageSize = 1000
    • Удалить mySearcher.SizeLimit = int.MaxValue
  2. Вы можете использовать Tuple - http://msdn.microsoft.com/en-us/library/system.tuple(VS.90).aspx. Или просто определить пользовательский класс в качестве значения и затем объявить Dictionary в качестве словаря:

    publicclass LogonTimeStamps {

    public long LastLogon {get;задавать;}

    public long LastLogonTimeStamp {get;задавать;}

    }

  3. Для словаря используйте myDictionary.ContainsKey(yourKey).Для AD вы должны использовать result.Properties.Contains("yourAttribute").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...