Уведомление об изменении в Active Directory (выборочные атрибуты) C#
Подскажите пожалуйста, пытаюсь реализовать получение уведомлений из AD методом который описан Райана Данна. Немного его доработав для своих нужд. Вопросов будет 2.
- Как сделать чтоб уведомления приходили об изменениях не от всех атрибутах? Так как при авторизации клиента на рабочей машине так же приводит к изменениям атрибутов. Хотелось бы отслеживать только определенный массив атрибутов.
- Так же вопрос по поводу
notifier.Register("OU=Home, DC=home, DC=local", SearchScope.Subtree);, а именно SearchScope.Subtree, Subtree - приводит к получения всех изменений, Base - изменения только в базовом OU, OneLevel - в базовом и дочернем OU. Но работает только Subtree, а это очень много уведомлений.
Код программы:
static void Main(string[] args)
{
try
{
LdapDirectoryIdentifier idi = new LdapDirectoryIdentifier("192.168.0.11");
using (LdapConnection connect = new LdapConnection(idi))
{
connect.SessionOptions.ProtocolVersion = 3;
NetworkCredential nc = new NetworkCredential(@"Admin", "Q150+150");
connect.Bind(nc);
Console.WriteLine(nc);
using (ChangeNotifier notifier = new ChangeNotifier(connect))
{
//register some objects for notifications (limit 5)
notifier.Register("DC=home, DC=local", SearchScope.Subtree);
//notifier.Register("OU=Home, DC=home, DC=local", SearchScope.OneLevel);
notifier.ObjectChanged += new EventHandler<ObjectChangedEventArgs>(notifier_ObjectChanged);
Console.WriteLine("Waiting for changes...");
Console.WriteLine();
Console.ReadLine();
}
}
}
catch (LdapException e)
{
Console.WriteLine("\r\nUnable to login:\r\n\t" + e.Message);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine("\r\nUnexpected exception occured:\r\n\t" + e.GetType() + ":" + e.Message);
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();
}
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)
{
string[] attribs = new string[]{
"distinguishedName",
"sAMAccountName",
"name",
"mail",
"mobile"};
SearchRequest request = new SearchRequest(
dn, //root the search here
"(objectClass=*)", //very inclusive
scope, //any scope works
attribs //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; }
}
}