2010-01-04 1 views
8

Эта ссылка http://msdn.microsoft.com/en-us/library/aa772153(VS.85).aspx говорит:Регистрация уведомлений об изменениях с Active Directory с помощью C#

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

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

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

Спасибо.

ответ

12

Я не уверен, что это то, что вам нужно, но взглянуть на http://dunnry.com/blog/ImplementingChangeNotificationsInNET.aspx

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



Есть три способа выяснение вещей, которые были изменены в Active Directory (или ADAM).   Они были зарегистрированы в течение некоторого времени по крайней MSDN в точно названный "Overview of Change Tracking Techniques"   В итоге:..

  1. Polling for Changes using uSNChanged Этот метод проверяет значение в„highestCommittedUSN“, чтобы начать, а затем выполняет поиск для значений„uSNChanged“, которые выше, впоследствии   Атрибут 'uSNChanged' не реплицируется между контроллерами домена, поэтому вы должны каждый раз возвращаться к одному контроллеру домена для согласованности.   По существу, вы выполняете поиск, который ищет наивысшее значение «uSNChanged» + 1, а затем читает в результаты, отслеживающие их любым способом.
    • Преимущества
      • Это самый удобный способ.   Все языки и 11-разрядные версии .NET поддерживают этот путь, поскольку это простой поиск.
    • Недостатки
      • Существует много возможностей для разработчиков, о которых следует заботиться.   Вы возвращаете весь объект обратно, и вы должны определить, что изменилось на объекте (и если вам интересно об этом изменении).
      • Работа с удаленными объектами - это боль.
      • Это метод опроса, так что это только в режиме реального времени, как часто вы запрашиваете.   Это может быть хорошей вещью в зависимости от приложения. Обратите внимание, что промежуточные значения здесь также не отслеживаются.
  2. Polling for Changes Using the DirSync Control.   Этот метод использует параметр ADS_SEARCHPREF_DIRSYNC в ADSI и элемент управления LDAP_SERVER_DIRSYNC_OID под обложками.   Просто выполните начальный поиск, сохраните файл cookie, а затем снова выполните поиск и отправьте файл cookie.   Он вернет только те объекты, которые были изменены.
    • Преимущества
      • Это простая модель для подражания.   Обе системы.DirectoryServices и System.DirectoryServices.Protocols поддерживают этот параметр.
      • Фильтрация может уменьшить то, что вам нужно, чтобы беспокоиться.   В качестве примера, если мой первоначальный поиск для всех пользователей «(objectClass = user)», я могу впоследствии фильтровать при опросе с помощью «(sn = dunn)» и возвращать только комбинацию обоих фильтров вместо того, чтобы иметь дело со всем, начиная с основного фильтра.
      • Опция Windows 2003+ удаляет административное ограничение для использования этой опции (защита объекта).
      • Опция Windows 2003+ также даст вам возможность возвращать только инкрементные значения, которые были изменены в больших многозначных атрибутах.   Это действительно приятная функция.
      • Хорошо работает с удаленными объектами.
    • Недостатки
      • Это вариант .NET 2.0+ или более поздней версии.   Пользователям .NET 1.1 необходимо будет использовать отслеживание uSNChanged.   Языки сценариев не могут использовать этот метод.
      • Вы можете использовать только поиск в разделе.   Если вы хотите отслеживать только определенное подразделение или объект, вы должны сами решить эти результаты самостоятельно.
      • Использование этого режима в доменах, отличных от Windows 2003, с ограничением на то, что вы должны иметь репликацию, получать разрешения на изменение (по умолчанию только администратор) для использования.
      • Это метод опроса.   Он также не отслеживает промежуточные значения.   Итак, если объект, который вы хотите отслеживать изменения между поисками несколько раз, вы получите только последнее изменение.   Это может быть преимуществом в зависимости от приложения.
  3. Change Notifications in Active Directory.   Этот метод регистрирует поиск в отдельном потоке, который будет получать уведомления при изменении любого объекта, соответствующего фильтру.   Вы можете зарегистрировать до 5 уведомлений на асинхронное соединение.
    • Преимущества
      • Мгновенное уведомление.   Другие методы требуют опроса.
      • Поскольку это уведомление, вы получите все изменения, даже промежуточные, которые были бы потеряны в двух других методах.
    • Недостатки
      • Относительно ресурсоемкие.   Вы не хотите делать целую тонну, так как это может вызвать проблемы с масштабируемостью с вашим контроллером.
      • Это только говорит о том, изменился объект, но он не говорит вам, что это за изменение.   Вам нужно выяснить, изменился ли ваш атрибут или нет.   Это, как говорится, довольно легко определить, был ли объект удален (проще, чем опрос uSNChanged).
      • Вы можете сделать это только в неуправляемом коде или в System.DirectoryServices.Protocols.

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

Моя первая мысль о написании этого заключается в использовании sample code, найденного на MSDN (и ссылка на опцию № 3), и просто преобразуйте его в System.DirectoryServices.Protocols.   Это оказалось тупиком.   Как вы это делаете в 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(); 
} 
+0

Это идеальное решение - большое спасибо за эту ссылку. – Sam

+0

@stuartd Итак, у меня есть эта работа, уведомления об изменении RXing и все. Но я возвращаюсь как 30 атрибутов, ни одна из которых не отличается от их текущей конфигурации. Я пропускаю часть, где мы можем получать только измененные предметы? – Wjdavis5

+0

@ Wjdavis5 вы должны задать новый вопрос. – stuartd

Смежные вопросы