سؤال

هذا الرابط http://msdn.microsoft.com/en-us/library/aa772153(VS.85).aspx. يقول:

يمكنك تسجيل ما يصل إلى خمس طلبات إعلام على اتصال LDAP واحد. يجب أن يكون لديك مؤشر ترابط مخصص ينتظر الإخطارات ويعالجها بسرعة. عند استدعاء دالة LDAP_Search_ext لتسجيل طلب إشعار، تقوم الدالة بإرجاع معرف الرسائل الذي يحدد هذا الطلب. يمكنك بعد ذلك استخدام وظيفة LDAP_RESUT لانتظار تغيير الإخطارات. عند حدوث تغيير، يرسل الخادم رسالة LDAP تحتوي على معرف الرسالة لطلب الإعلام الذي ولدت الإخطار. يؤدي هذا إلى العودة LDAP_RESUT للعودة إلى نتائج البحث التي تحدد الكائن الذي تم تغييره.

لا يمكنني العثور على سلوك مماثل يبحث من خلال وثائق .NET. إذا كان أي شخص يعرف كيفية القيام بذلك في C # سأكون ممتنا للغاية لمعرفة. أنا أتطلع إلى معرفة متى يتم تغيير السمات على جميع المستخدمين في النظام حتى أتمكن من إجراء إجراءات مخصصة حسب ما تغير.

لقد بحثت من خلال Stackoverflow وغيرها من المصادر دون حظ.

شكرا.

هل كانت مفيدة؟

المحلول

لست متأكدا من الأمر الذي تحتاجه، ولكن إلقاء نظرة على http://dunnry.com/blog/implementingchangenotiquotIctionsinnet.aspx.

تحرير: إضافة نص ورمز من المقالة:



هناك ثلاث طرق لمعرفة الأشياء التي تغيرت في Active Directory (أو ADAM). تم توثيق هذه لبعض الوقت في MSDN في بعنوان "نظرة عامة على تقنيات تتبع التغيير "وبعد باختصار:

  1. الاقتراع للتغييرات باستخدام USNChanged. وبعد تتحقق هذه التقنية قيمة "أعلى الصفحة" للبدء ثم تنفذ عمليات البحث عن قيم "USNChanged" التي هي أعلى بعد ذلك. لا يتم نسخ سمة "USNChanged" نسخ متماثل بين وحدات التحكم بالمجال، لذلك يجب أن تعود إلى نفس وحدة تحكم المجال في كل مرة للاتساق. أساسا، تقوم بإجراء عملية بحث تبحث عن أعلى قيمة "USNChanged" + 1 ثم اقرأ في النتائج التي تتبعها بأي طريقة ترغب فيها.
    • فوائد
      • هذه هي الطريقة الأكثر توافقا. جميع اللغات وجميع إصدارات دعم .NET بهذه الطريقة لأنه بحث بسيط.
    • سلبيات
      • هناك الكثير هنا للمطور لرعاية. تحصل على الكائن بالكامل مرة أخرى، ويجب عليك تحديد ما الذي يتغير على الكائن (وإذا كنت تهتم بهذا التغيير).
      • التعامل مع الكائنات المحذوفة هو ألم.
      • هذه تقنية الاقتراع، لذلك فقط في الوقت الفعلي كمثير من المرات التي تستعلم بها. هذا يمكن أن يكون شيئا جيدا اعتمادا على التطبيق. ملاحظة، لا يتم تتبع القيم المتوسطة هنا أيضا.
  2. الاقتراع للتغييرات باستخدام عنصر تحكم Dirsyncوبعد تستخدم هذه التقنية خيار ADS_SearchPref_Dirsync في ADSI والتحكم LDAP_SERVER_DIRSYNC_OID تحت الأغطية. ما عليك سوى إجراء بحث أولي، وتخزين ملف تعريف الارتباط، ثم ابحث في وقت لاحق مرة أخرى وإرسال ملف تعريف الارتباط. سيعود فقط الكائنات التي تغيرت.
    • فوائد
      • هذا هو نموذج سهل لمتابعة. كل من system.directoryservices و system.directoryservices.protocols دعم هذا الخيار.
      • تصفية يمكن أن تقلل من ما تحتاج إلى تهتم. كمثال، إذا كان بحثي الأولي هو لجميع المستخدمين "(ObjectClass = المستخدم)"، فيمكنني مرشح لاحقا على الاقتراع مع "(SN = DUNN)" ولم أعود فقط إلى مزيج من كل من المرشحات، بدلا من الاضطرار إلى التعامل معه كل شيء من المرشح الأنسالي.
      • يقوم خيار Windows 2003+ بإزالة القيد الإداري لاستخدام هذا الخيار (أمان كائن).
      • سيعطيك خيار Windows 2003+ أيضا القدرة على العودة فقط القيم الإضافية التي تغيرت في سمات كبيرة متعددة القيمة. هذه ميزة لطيفة حقا.
      • صفقات جيدة مع الكائنات المحذوفة.
    • سلبيات
      • يمكنك فقط النطاق البحث في قسم. إذا كنت ترغب في تتبع OU أو كائن معين فقط، يجب عليك فرز تلك النتائج في وقت لاحق.
      • إن استخدام هذا مع مجالات وضع عدم نظام التشغيل Windows 2003 يأتي مع التقييد الذي يجب أن يكون لديك النسخ المتماثل الحصول على أذونات تغيير الأذونات (المسؤول الافتراضي فقط) للاستخدام.
      • هذه هي تقنية الاقتراع. لا تتبع القيم الوسيطة أيضا. لذلك، إذا كان الكائن الذي تريد تتبع التغييرات بين عمليات البحث عدة مرات، فستحصل فقط على التغيير الأخير. يمكن أن يكون هذا ميزة اعتمادا على التطبيق.
  3. تغيير الإخطارات في Active Directoryوبعد تقوم هذه التقنية بتسجيل البحث في مؤشر ترابط منفصل سيتلقى إعلامات عند أي تغييرات كائن يطابق المرشح. يمكنك تسجيل ما يصل إلى 5 إخطارات لكل اتصال ASYNC.
    • فوائد
      • إخطار فوري. التقنيات الأخرى تتطلب الاقتراع.
      • لأن هذا إشعار، ستحصل على جميع التغييرات، حتى تلك الوسيطة التي قد فقدت في التقنيين الآخرين.
    • سلبيات
      • كثيفة الموارد نسبيا. لا تريد أن تفعل طن كامل من هذه لأنها قد تسبب مشاكل قابلية للتحميل مع جهاز التحكم الخاص بك.
      • يخبرك هذا فقط إذا تغير الكائن، لكنه لا يخبرك بما كان التغيير. تحتاج إلى معرفة ما إذا كانت السمة التي تهتم بها قد تغير أم لا. ومع ذلك، من السهل معرفة ما إذا كان قد حذف الكائن (أسهل من الاقتراع USNChanged على الأقل).
      • يمكنك فقط القيام بذلك في التعليمات البرمجية غير المدارة أو مع system.directoryservices.protocols.

بالنسبة للجزء الأكبر، وجدت أن Dirsync تناسب مشروع القانون بالنسبة لي في كل موقف تقريبا. لم أزعجني أبدا تجربة أي من التقنيات الأخرى. ومع ذلك، سأل القارئ عما إذا كانت هناك طريقة للقيام بإخطارات التغيير في .NET. احسبت أنه كان من الممكن استخدام SDS.P، لكنه لم يحاول ذلك أبدا. اتضح، فمن الممكن ولا في الواقع من الصعب جدا القيام به.

فكرتي الأولى في كتابة هذا كان لاستخدام عينة من الرموز وجدت على 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();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top