我不知道它做你需要什么,但看看http://dunnry.com/blog/ImplementingChangeNotificationsInNET.aspx
编辑:添加的文本,然后从文章代码:
有三种方式弄清楚在Active Directory(或ADAM)中发生了变化的事情。 。
- Polling for Changes using uSNChanged该技术检查‘highestCommittedUSN’值开始,然后关于‘uSNChanged’值是高随后执行搜索: 这些都在恰当地名为“Overview of Change Tracking Techniques" 总之被记录在一段时间上在MSDN 'uSNChanged'属性不在域控制器之间复制,因此每次必须返回到相同的域控制器才能保持一致性。 本质上,您执行搜索以查找最高'uSNChanged'值+ 1,然后读入结果以您希望的任何方式跟踪它们
- 好处
- 这是最兼容的方式 所有语言和a因为这是一个简单的搜索,因此这种方式支持.NET的.NET版本。
- 缺点
- 开发者有很多需要照顾的地方。 您得到整个对象,并且必须确定对象上发生了什么变化(并且如果您关心该变化)。
- 处理已删除的对象是一种痛苦。
- 这是一种轮询技术,因此它只与您查询的频率一样实时。 这可能是一件好事,取决于应用程序。请注意,中间值也不在这里跟踪。
- Polling for Changes Using the DirSync Control。 此技术使用ADSI中的ADS_SEARCHPREF_DIRSYNC选项和封面下的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 Tracking。 脚本语言不能使用此方法。
- 您只能将搜索范围限定到分区。 如果您只想跟踪特定的OU或对象,则必须稍后自行整理这些结果。
- 在非Windows 2003模式域中使用此限制带有限制,即必须具有要使用的复制获取更改权限(仅默认为admin)。
- 这是一个轮询技术。 它也不跟踪中间值。 因此,如果您想追踪多次搜索之间的变化,只会得到最后一次更改。 这可能是一个优势,取决于应用程序。
- Change Notifications in Active Directory。 此技术在单独的线程上注册搜索,当任何对象与筛选器匹配发生更改时将收到通知。 每个异步连接最多可以注册5个通知。
- 好处
- 即时通知。 其他技术需要轮询。
- 因为这是一个通知,所以你会得到所有的改变,甚至是在其他两种技术中会丢失的中间变化。
- 缺点
- 资源相对。 您不希望完成这些操作,因为这可能会导致控制器出现可扩展性问题。
- 这只会告诉你对象是否已经改变,但它不会告诉你改变是什么。 您需要弄清楚您关心的属性是否已更改。 这就是说,很容易判断对象是否已被删除(至少比uSNChanged轮询更容易)。
- 您只能在非托管代码或System.DirectoryServices.Protocols中执行此操作。
大多数情况下,我发现DirSync几乎适用于所有情况下的账单。 我从来没有想过尝试任何其他技术。 但是,读者询问是否有方法在.NET中执行更改通知。 我觉得可以使用SDS.P,但从未尝试过。 原来,这可能并且实际上并不难。
我写这篇文章的第一个想法是使用MSDN上的sample code(并从选项#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();
}
这是完美的 - 非常感谢你的这个链接。 – Sam 2010-01-05 15:02:12
@stuartd所以我有这个工作,RXing更改通知和所有。但是我回到了30个属性,其中没有一个与他们当前的配置不同。我是否错过了我们只能接收更改项目的部分? – Wjdavis5 2014-07-18 11:25:14
@ Wjdavis5你应该问一个新问题。 – stuartd 2014-07-18 13:57:17