Регистрация уведомления об изменениях в Active Directory с помощью C#

по этой ссылке http://msdn.microsoft.com/en-us/library/aa772153(против.85).аспн говорит:

вы можете зарегистрировать до пяти запросов уведомлений на одном соединении LDAP. У вас должен быть выделенный поток, который ждет уведомлений и быстро их обрабатывает. При вызове функции ldap_search_ext для регистрации запроса уведомления функция возвращает идентификатор сообщения, идентифицирующий этот запрос. Затем вы используете функцию ldap_result для ожидания уведомление об изменении. При изменении сервер отправляет вам сообщение LDAP, содержащее идентификатор сообщения для запроса уведомления, который сгенерировал уведомление. Это приводит к возвращению функции ldap_result с результатами поиска, идентифицирующими измененный объект.

Я не могу найти аналогичное поведение, просматривая документацию .NET. Если кто-нибудь знает, как это сделать на C#, я был бы очень признателен. Я ищу, чтобы увидеть, когда атрибуты меняются на всех пользователи в системе, поэтому я могу выполнять пользовательские действия в зависимости от того, что изменилось.

Я просмотрел stackoverflow и другие источники без везения.

спасибо.

1 ответов


Я не уверен, что он делает то, что вам нужно, но посмотрите на http://dunnry.com/blog/ImplementingChangeNotificationsInNET.aspx

Edit: добавлен текст и код из статьи:



есть три способа выяснить, что изменилось в Active Directory (или ADAM).  Они были задокументированы в течение некоторого времени в MSDN в метко озаглавленном"обзор методов отслеживания изменений".  В резюме:

  1. опрос изменений с помощью uSNChanged. Этот метод проверяет значение "highestCommittedUSN" для запуска, а затем выполняет поиск значений "uSNChanged", которые впоследствии выше.  Атрибут "uSNChanged" не реплицируется между контроллерами домена, поэтому для обеспечения согласованности необходимо каждый раз возвращаться к одному контроллеру домена.  По сути, вы выполняете поиск самого высокого значения "uSNChanged" + 1, а затем читаете результаты отслеживать их любым способом.
    • преимущества
      • это самый совместимый способ.  Все языки и все версии .NET поддерживают этот способ, так как это простой поиск.
    • недостатки
      • есть много здесь для разработчика, чтобы заботиться.  Вы получаете весь объект, а вы должны определить, что изменилось на объекте (и если вы заботитесь об этом изменении).
      • работа с удаленными объекты-это боль.
      • это метод опроса, так что это только в режиме реального времени, как часто вы запрашиваете.  Это может быть хорошо, в зависимости от приложения. Обратите внимание, что промежуточные значения здесь также не отслеживаются.
  2. опрос изменений с помощью элемента управления DirSync.  Этот метод использует параметр ADS_SEARCHPREF_DIRSYNC в ADSI и элемент управления LDAP_SERVER_DIRSYNC_OID под обложками.  Просто сделайте инициал найдите, сохраните файл cookie, а затем снова выполните поиск и отправьте файл cookie.  Он вернет только те объекты, которые изменились.
    • преимущества
      • это простая модель, чтобы следовать.  обе системы.Каталог и система.DirectoryServices.Протоколы поддерживают эту опцию.
      • фильтрация может уменьшить то, что вам нужно беспокоиться.  Например, если мой первоначальный поиск предназначен для всех пользователей "(objectClass=user)", я могу впоследствии фильтровать опрос с помощью "(sn=dunn) " и только вернуть комбинацию обоих фильтров, вместо того, чтобы иметь дело со всем из внутреннего фильтра.
      • Windows 2003+ опция удаляет административное ограничение для использования этой опции (безопасность объекта).
      • Windows 2003+ option также даст вам возможность возвращать только инкрементные значения, которые изменились в больших многозначных атрибутах.  Это действительно хорошая функция.
      • хорошо справляется с удаленными объектами.
    • недостатки
      • это .NET 2.0+ или более поздней версии только вариант.  Пользователям .NET 1.1 необходимо будет использовать отслеживание uSNChanged.  Языки сценариев не могут использовать этот метод.
      • вы можете только область поиска до раздела.  Если вы хотите отслеживать только определенный OU или объект, вы должны отсортировать эти результаты позже.
      • использование этого с доменами не Windows 2003 mode поставляется с ограничением, которое необходимо иметь репликация получить разрешения на изменения (по умолчанию только администратор) для использования.
      • это техника опроса.  Он также не отслеживает промежуточные значения.  Так, если объект, который вы хотите отслеживать изменения в поиск несколько раз, вы получите только последнее изменение.  Это может быть преимуществом в зависимости от применения.
  3. изменить уведомления в Active Directory.  Этот метод регистрирует поиска отдельный поток, который будет получать уведомления при изменении любого объекта, соответствующего фильтру.  Вы можете зарегистрировать до 5 уведомлений на асинхронное соединение.
    • преимущества
      • мгновенные уведомления.  Другие методы требуют опроса.
      • поскольку это уведомление, вы получите все изменения, даже промежуточные, которые были бы потеряны в двух других методах.
    • недостатки
      • относительно ресурсоемким.  Вы не хотите делать целую тонну из них, поскольку это может вызвать проблемы масштабируемости с вашим контроллером.
      • это только говорит вам, если объект изменился,но он не говорит вам, что изменение было.  Вам нужно выяснить, изменился ли атрибут, о котором вы заботитесь, или нет.  При этом довольно легко сказать, был ли объект удален (проще, чем usnchanged polling по крайней мере).
      • вы можете только сделать это в неуправляемом коде или с системой.DirectoryServices.Протоколы.

по большей части, я обнаружил, что DirSync подходит для меня практически в каждой ситуации.  Я никогда не утруждал себя попытками использовать другие методы.  Однако читатель спросил, есть ли способ сделать уведомления об изменениях .Сеть. Я подумал, что это возможно с помощью SDS.P, но никогда не пробовал.  Оказывается, это возможно и на самом деле не слишком сложно делать.

моей первой мыслью при написании этого было использовать пример кода найдено на MSDN (и ссылается на опцию #3) и просто преобразовать это в систему.DirectoryServices.Протоколы.  Это оказалось тупиком.  То, как вы это делаете в SDS.P и то, как работает Пример кода, достаточно различны, чтобы это не помогло.  Вот решение, которое я придумал:

public class ChangeNotifier : IDisposable
{
    LdapConnection _connection;
    HashSet<IAsyncResult> _results = new HashSet<IAsyncResult>();

    public ChangeNotifier(LdapConnection connection)
    {
        _connection = connection;
        _connection.AutoBind = true;
    }

    public void Register(string dn, SearchScope scope)
    {
        SearchRequest request = new SearchRequest(
            dn, //root the search here
            "(objectClass=*)", //very inclusive
            scope, //any scope works
            null //we are interested in all attributes
            );

        //register our search
        request.Controls.Add(new DirectoryNotificationControl());

        //we will send this async and register our callback
        //note how we would like to have partial results

        IAsyncResult result = _connection.BeginSendRequest(
            request,
            TimeSpan.FromDays(1), //set timeout to a day...
            PartialResultProcessing.ReturnPartialResultsAndNotifyCallback,
            Notify,
            request);

        //store the hash for disposal later

        _results.Add(result);
    }

    private void Notify(IAsyncResult result)
    {
        //since our search is long running, we don't want to use EndSendRequest
        PartialResultsCollection prc = _connection.GetPartialResults(result);

        foreach (SearchResultEntry entry in prc)
        {
            OnObjectChanged(new ObjectChangedEventArgs(entry));
        }
    }

    private void OnObjectChanged(ObjectChangedEventArgs args)
    {
        if (ObjectChanged != null)
        {
            ObjectChanged(this, args);
        }
    }

    public event EventHandler<ObjectChangedEventArgs> ObjectChanged;

    #region IDisposable Members

    public void Dispose()
    {
        foreach (var result in _results)
        {
            //end each async search
            _connection.Abort(result);

       }
    }

    #endregion
}


public class ObjectChangedEventArgs : EventArgs
{
    public ObjectChangedEventArgs(SearchResultEntry entry)
    {
        Result = entry;
    }

    public SearchResultEntry Result { get; set;}
}

это относительно простой класс, который можно использовать для регистрации поиска. Фокус в том, использование метода GetPartialResults в методе обратного вызова для получения только что произошедшего изменения. Я также включил очень упрощенный класс EventArgs, который я использую для передачи результатов. Обратите внимание, что я ничего не делаю о потоковой передаче здесь, и у меня нет обработки ошибок (это всего лишь образец). Вы можете использовать этот класс следующим образом:

static void Main(string[] args)
{
    using (LdapConnection connect = CreateConnection("localhost"))
    {
        using (ChangeNotifier notifier = new ChangeNotifier(connect))
        {
            //register some objects for notifications (limit 5)
            notifier.Register("dc=dunnry,dc=net", SearchScope.OneLevel);
            notifier.Register("cn=testuser1,ou=users,dc=dunnry,dc=net", SearchScope.Base);

            notifier.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(notifier_ObjectChanged);

            Console.WriteLine("Waiting for changes...");
            Console.WriteLine();
            Console.ReadLine();
        }
    }
}


static void notifier_ObjectChanged(object sender, ObjectChangedEventArgs e)
{
    Console.WriteLine(e.Result.DistinguishedName);

    foreach (string attrib in e.Result.Attributes.AttributeNames)
    {
        foreach (var item in e.Result.Attributes[attrib].GetValues(typeof(string)))
        {
            Console.WriteLine("\t{0}: {1}", attrib, item);
        }
    }
    Console.WriteLine();
    Console.WriteLine("====================");
    Console.WriteLine();
}