Регистрация уведомления об изменениях в 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 в метко озаглавленном"обзор методов отслеживания изменений". В резюме:
-
опрос изменений с помощью uSNChanged. Этот метод проверяет значение "highestCommittedUSN" для запуска, а затем выполняет поиск значений "uSNChanged", которые впоследствии выше. Атрибут "uSNChanged" не реплицируется между контроллерами домена, поэтому для обеспечения согласованности необходимо каждый раз возвращаться к одному контроллеру домена. По сути, вы выполняете поиск самого высокого значения "uSNChanged" + 1, а затем читаете результаты отслеживать их любым способом.
- преимущества
- это самый совместимый способ. Все языки и все версии .NET поддерживают этот способ, так как это простой поиск.
- недостатки
- есть много здесь для разработчика, чтобы заботиться. Вы получаете весь объект, а вы должны определить, что изменилось на объекте (и если вы заботитесь об этом изменении).
- работа с удаленными объекты-это боль.
- это метод опроса, так что это только в режиме реального времени, как часто вы запрашиваете. Это может быть хорошо, в зависимости от приложения. Обратите внимание, что промежуточные значения здесь также не отслеживаются.
- преимущества
-
опрос изменений с помощью элемента управления 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 поставляется с ограничением, которое необходимо иметь репликация получить разрешения на изменения (по умолчанию только администратор) для использования.
- это техника опроса. Он также не отслеживает промежуточные значения. Так, если объект, который вы хотите отслеживать изменения в поиск несколько раз, вы получите только последнее изменение. Это может быть преимуществом в зависимости от применения.
- преимущества
-
изменить уведомления в 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();
}