2010-01-04 25 views
8

Liên kết này http://msdn.microsoft.com/en-us/library/aa772153(VS.85).aspx nói:Đăng ký thông báo thay đổi với Active Directory bằng C#

Bạn có thể đăng ký tối đa năm yêu cầu thông báo trên một kết nối LDAP. Bạn phải có một chuỗi chuyên dụng chờ thông báo và xử lý chúng một cách nhanh chóng. Khi bạn gọi hàm ldap_search_ext để đăng ký một yêu cầu thông báo, hàm trả về một định danh thông báo nhận dạng yêu cầu đó. Sau đó, bạn sử dụng hàm ldap_result để chờ thông báo thay đổi. Khi một thay đổi xảy ra, máy chủ sẽ gửi cho bạn một tin nhắn LDAP chứa thông tin nhận dạng tin nhắn cho yêu cầu thông báo đã tạo thông báo. Điều này làm cho hàm ldap_result trở lại với kết quả tìm kiếm xác định đối tượng đã thay đổi.

Tôi không thể tìm thấy hành vi tương tự đang xem qua tài liệu .NET. Nếu bất cứ ai biết làm thế nào để làm điều này trong C# Tôi rất biết ơn để biết. Tôi đang tìm kiếm để xem khi nào các thuộc tính thay đổi trên tất cả người dùng trong hệ thống để tôi có thể thực hiện các tác vụ tùy chỉnh tùy thuộc vào những gì đã thay đổi.

Tôi đã xem qua stackoverflow và các nguồn khác không có may mắn.

Cảm ơn.

Trả lời

12

Tôi không chắc chắn nó làm những gì bạn cần, nhưng có một cái nhìn tại http://dunnry.com/blog/ImplementingChangeNotificationsInNET.aspx

Chỉnh sửa: Thêm văn bản và mã từ bài viết:



Có ba cách tìm ra những thứ đã thay đổi trong Active Directory (hoặc ADAM).   Những đã được ghi nhận trong một thời gian qua tại MSDN trong aptly có tiêu đề "Overview of Change Tracking Techniques"   Nói tóm lại:..

  1. Polling for Changes using uSNChanged Kỹ thuật này sẽ kiểm tra giá trị của highestCommittedUSN 'để bắt đầu và sau đó thực hiện tìm kiếm các giá trị 'uSNChanged' mà là cao hơn sau đó   Thuộc tính 'uSNChanged' không được sao chép giữa các bộ điều khiển miền, vì vậy bạn phải quay lại cùng một bộ điều khiển miền mỗi lần để thống nhất.   Về cơ bản, bạn thực hiện tìm kiếm tìm giá trị 'uSNChanged' cao nhất + 1 và sau đó đọc các kết quả theo dõi chúng theo bất kỳ cách nào bạn muốn.
    • Lợi ích
      • Đây là cách tương thích nhất   Tất cả các ngôn ngữ và một các phiên bản .NET hỗ trợ theo cách này vì nó là một tìm kiếm đơn giản.
    • Nhược điểm
      • Có rất nhiều thứ để nhà phát triển quản lý.   Bạn nhận lại toàn bộ đối tượng và bạn phải xác định những gì đã thay đổi trên đối tượng (và nếu bạn quan tâm đến thay đổi đó).
      • Xử lý các đối tượng đã xóa là một cơn đau.
      • Đây là kỹ thuật bỏ phiếu, vì vậy nó chỉ là thời gian thực như tần suất bạn truy vấn.   Điều này có thể là một điều tốt tùy thuộc vào ứng dụng. Lưu ý, giá trị trung gian không được theo dõi ở đây.
  2. Polling for Changes Using the DirSync Control.   Kỹ thuật này sử dụng tùy chọn ADS_SEARCHPREF_DIRSYNC trong ADSI và điều khiển LDAP_SERVER_DIRSYNC_OID bên dưới nắp.   Chỉ cần thực hiện tìm kiếm ban đầu, lưu trữ cookie và sau đó tìm kiếm lại và gửi cookie.   Nó sẽ chỉ trả lại các đối tượng đã thay đổi.
    • Lợi ích
      • Đây là mô hình dễ theo dõi.   Cả hai hệ thống.DirectoryServices và System.DirectoryServices.Protocols hỗ trợ tùy chọn này.
      • Lọc có thể làm giảm những gì bạn cần phải bận tâm.   Ví dụ: nếu tìm kiếm ban đầu của tôi dành cho tất cả người dùng "(objectClass = user)", sau đó tôi có thể lọc bỏ phiếu bằng "(sn = dunn)" và chỉ lấy lại kết hợp cả hai bộ lọc thay vì phải xử lý với mọi thứ từ bộ lọc intial.
      • Tùy chọn Windows 2003+ loại bỏ giới hạn hành chính để sử dụng tùy chọn này (bảo mật đối tượng).
      • Tùy chọn Windows 2003+ cũng sẽ cung cấp cho bạn khả năng chỉ trả lại các giá trị gia tăng đã thay đổi trong các thuộc tính có giá trị lớn.   Đây là một tính năng thực sự tốt đẹp.
      • Ưu đãi tốt với các đối tượng đã xóa.
    • Nhược điểm
      • Đây là tùy chọn .NET 2.0+ hoặc mới hơn.   Người dùng .NET 1.1 sẽ cần sử dụng tính năng Theo dõi uSNChanged.   Ngôn ngữ lập trình không thể sử dụng phương pháp này.
      • Bạn chỉ có thể phạm vi tìm kiếm cho một phân vùng.   Nếu bạn chỉ muốn theo dõi một OU hoặc đối tượng cụ thể, bạn phải tự mình sắp xếp các kết quả đó sau.
      • Sử dụng tính năng này với các miền chế độ không thuộc Windows 2003 đi kèm với hạn chế mà bạn phải có bản sao nhận quyền thay đổi (mặc định chỉ quản trị viên) để sử dụng.
      • Đây là kỹ thuật bỏ phiếu.   Nó cũng không theo dõi các giá trị trung gian.   Vì vậy, nếu một đối tượng bạn muốn theo dõi các thay đổi giữa các lần tìm kiếm, bạn sẽ chỉ nhận được thay đổi cuối cùng.   Đây có thể là một lợi thế tùy thuộc vào ứng dụng.
  3. Change Notifications in Active Directory.   Kỹ thuật này đăng ký tìm kiếm trên một chuỗi riêng biệt sẽ nhận thông báo khi có bất kỳ thay đổi đối tượng nào phù hợp với bộ lọc.   Bạn có thể đăng ký tối đa 5 thông báo cho mỗi kết nối không đồng bộ.
    • Lợi ích
      • Thông báo tức thì.   Các kỹ thuật khác yêu cầu bỏ phiếu.
      • Vì đây là thông báo, bạn sẽ nhận được tất cả thay đổi, ngay cả những thay đổi trung gian đã bị mất trong hai kỹ thuật còn lại.
    • Nhược điểm
      • Tài nguyên tương đối chuyên sâu.   Bạn không muốn làm cả tấn vì chúng có thể gây ra vấn đề về khả năng mở rộng với bộ điều khiển của bạn.
      • Điều này chỉ cho bạn biết nếu đối tượng đã thay đổi, nhưng nó không cho bạn biết thay đổi là gì.   Bạn cần phải tìm hiểu xem thuộc tính bạn quan tâm có thay đổi hay không.   Điều đó đang được nói, nó là khá dễ dàng để biết nếu đối tượng đã bị xóa (dễ dàng hơn uSNChanged polling ít nhất).
      • Bạn chỉ có thể thực hiện việc này trong mã không được quản lý hoặc bằng System.DirectoryServices.Protocols.

Đối với hầu hết các phần, tôi đã nhận thấy rằng DirSync đã phù hợp với hóa đơn cho tôi trong hầu như mọi tình huống.   Tôi chưa bao giờ bận tâm thử bất kỳ kỹ thuật nào khác.   Tuy nhiên, một độc giả hỏi có cách nào để thực hiện các thông báo thay đổi trong .NET không.   Tôi nghĩ rằng nó có thể sử dụng SDS.P, nhưng chưa bao giờ thử nó.   Biến ra, có thể và thực sự không quá khó để làm.

Suy nghĩ đầu tiên của tôi về cách viết này là sử dụng sample code được tìm thấy trên MSDN (và được tham chiếu từ tùy chọn # 3) và chỉ cần chuyển đổi thành System.DirectoryServices.Protocols.   Điều này hóa ra là một kết thúc chết.   Cách bạn làm điều đó trong SDS.P và cách mã mẫu hoạt động khác nhau đến nỗi nó không giúp được gì.  Đây là giải pháp mà tôi đã đưa ra:

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;} 
} 

Đây là một lớp tương đối đơn giản mà bạn có thể sử dụng để đăng ký tìm kiếm. Bí quyết là sử dụng phương pháp GetPartialResults trong phương thức gọi lại để chỉ nhận thay đổi vừa xảy ra. Tôi cũng đã bao gồm lớp EventArgs rất đơn giản mà tôi đang sử dụng để chuyển kết quả trở lại. Lưu ý, tôi không làm bất cứ điều gì về luồng ở đây và tôi không có bất kỳ xử lý lỗi (đây chỉ là một mẫu). Bạn có thể sử dụng lớp học này như vậy:

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

Điều này là hoàn hảo - cảm ơn bạn rất nhiều vì liên kết này. – Sam

+0

@stuartd Vì vậy, tôi có thông báo thay đổi đang hoạt động, RXing này và tất cả. Nhưng tôi quay trở lại như 30 thuộc tính, không có thuộc tính nào khác với cấu hình hiện tại của chúng. Tôi có thiếu phần mà chúng tôi chỉ có thể nhận được các mục đã thay đổi không? – Wjdavis5

+0

@ Wjdavis5 bạn nên đặt một câu hỏi mới. – stuartd

Các vấn đề liên quan