Domanda

Questo link http://msdn.microsoft.com /en-us/library/aa772153(VS.85).aspx dice:

È possibile registrare fino a cinque richieste di notifica su una singola connessione LDAP. È necessario disporre di un thread dedicato che attende le notifiche e li elabora rapidamente. Quando si chiama la funzione ldap_search_ext per registrare una richiesta di notifica, la funzione restituisce un identificatore di messaggio che identifica tale richiesta. È quindi utilizzare la funzione ldap_result di aspettare per le notifiche di modifica. Quando si verifica un cambiamento, il server invia un messaggio LDAP che contiene l'identificatore del messaggio per la richiesta di notifica che ha generato la notifica. Questo fa sì che la funzione ldap_result di tornare con i risultati della ricerca che identificano l'oggetto che ha cambiato.

Non riesco a trovare un comportamento simile guardando attraverso la documentazione di .NET. Se qualcuno sa come fare questo in C # sarei molto grato di sapere. Sto cercando di vedere quando gli attributi cambiano tutti gli utenti del sistema in modo da poter eseguire azioni personalizzate a seconda di cosa è cambiato.

Ho guardato attraverso StackOverflow e da altre fonti senza fortuna.

Grazie.

È stato utile?

Soluzione

Non sono sicuro che lo fa quello che ti serve, ma dare un'occhiata al http: // dunnry. com / blog / ImplementingChangeNotificationsInNET.aspx

Modifica: Aggiunta di testo e il codice da questo articolo:



Ci sono tre modi di capire cose che sono cambiate in Active Directory (o ADAM). Questi sono stati documentati da qualche tempo sopra a MSDN nel giustamente intitolato " Panoramica di rilevamento delle modifiche tecniche" . In sintesi:

  1. Polling per modifiche utilizzando uSNChanged . Questa tecnica controlla il valore 'highestCommittedUSN' per iniziare e poi esegue ricerche per i valori 'uSNChanged' che sono più alti in seguito. L'attributo 'uSNChanged' non viene replicata tra i controller di dominio, quindi è necessario tornare alla stesso controller di dominio ogni volta per coerenza. In sostanza, si esegue una ricerca cercando il più alto valore 'uSNChanged' + 1 e poi leggere nei risultati li monitoraggio in qualsiasi modo lo si desidera.
    • vantaggi
      • Questo è il modo più compatibile. Tutte le lingue e tutte le versioni di .NET supportano in questo modo in quanto si tratta di una semplice ricerca.
    • Svantaggi
      • C'è molto qui per lo sviluppatore di prendersi cura di. È possibile ottenere l'intero oggetto indietro, e si deve stabilire che cosa è cambiato per l'oggetto (e se vi preoccupate che il cambiamento).
      • Trattare con oggetti eliminati è un dolore.
      • Questa è una tecnica di polling, quindi è solo in tempo reale, come la frequenza con cui si esegue una query. Questo può essere una buona cosa a seconda dell'applicazione. Nota, valori intermedi non vengono monitorati neanche qui.
  2. Polling per modifiche utilizzando la sincronizzazione di directory di controllo . Questa tecnica utilizza l'opzione ADS_SEARCHPREF_DIRSYNC in ADSI ed il controllo LDAP_SERVER_DIRSYNC_OID sotto le coperte. Basta fare una ricerca iniziale, memorizzare il cookie, e poi cercare di nuovo e inviare il cookie. Si restituirà solo gli oggetti che sono stati modificati.
    • vantaggi
      • Questo è un modello facile da seguire. Entrambi System.DirectoryServices e System.DirectoryServices.Protocols supportano questa opzione.
      • Il filtraggio può ridurre ciò che è necessario preoccuparsi di. Per fare un esempio, se la mia ricerca iniziale è per tutti gli utenti "(objectClass = user)", posso successivamente filtro sul polling con "(sn = Dunn)" e solo tornare la combinazione di entrambi i filtri, invece di avere a che fare con tutto dal filtro intial.
      • opzione di Windows 2003+ rimuove il limite amministrativo per l'utilizzo di questa opzione (protezione degli oggetti).
      • opzione di Windows 2003+ vi darà anche la possibilità di restituire solo i valori incrementali che sono stati modificati in grandi attributi multivalore. Questa è una caratteristica veramente bello.
      • Offerte bene con oggetti eliminati.
    • Svantaggi
      • Questo è .NET 2.0+ o poi unica opzione. Gli utenti di .NET 1.1 sarà necessario utilizzare uSNChanged monitoraggio. Linguaggi di scripting non possono utilizzare questo metodo.
      • Puoi unico scopo la ricerca di una partizione. Se si desidera tenere traccia solo una particolare unità organizzativa o di un oggetto, è necessario risolvere quei risultati te più tardi.
      • L'utilizzo di questo con i domini modalità non-Windows 2003 viene fornito con la restrizione che è necessario disporre di replica ottenere modifiche permessi (default solo amministratore) da usare.
      • Questa è una tecnica di polling. Esso non tiene valori intermedi eitsua. Quindi, se un oggetto che si desidera tenere traccia delle modifiche tra le ricerche più volte, si otterrà solo l'ultima modifica. Questo può essere un vantaggio a seconda dell'applicazione.
  3. Notifiche Modifica in Directory attiva. Questa tecnica registra una ricerca su un thread separato che riceverà notifiche quando eventuali modifiche di oggetto che corrisponde al filtro. È possibile registrare fino a 5 le notifiche per connessione asincrona.
    • vantaggi
      • notifica istantanea. Le altre tecniche richiedono polling.
      • Poiché si tratta di una notifica, si otterrà tutti i cambiamenti, anche quelli intermedi che sarebbero andati perduti negli altri due tecniche.
    • Svantaggi
      • Relativamente di risorse. Non si vuole fare una tonnellata intera di questi in quanto potrebbe causare problemi di scalabilità con il controller.
      • Questo ti dice solo se l'oggetto è cambiato, ma non vi dico ciò che il cambiamento è stato. È necessario capire se l'attributo che ti interessa è cambiato o meno. Detto questo, è abbastanza facile dire se l'oggetto è stato eliminato (più facile che uSNChanged polling almeno).
      • È possibile farlo solo in codice non gestito o con System.DirectoryServices.Protocols.

Per la maggior parte, ho trovato che DirSync ha misura la fattura per me praticamente in ogni situazione. Non ho mai preso la briga di provare una qualsiasi delle altre tecniche. Tuttavia, un lettore ha chiesto se ci fosse un modo per fare le notifiche di modifica in .NET. Ho pensato che fosse possibile utilizzando SDS.P, ma non avevo mai provato. Si scopre, è possibile e in realtà non troppo difficile da fare.

Il mio primo pensiero sulla scrittura di questo è stato quello di utilizzare il codice di esempio trovato su MSDN ( e fa riferimento da opzione # 3) e semplicemente convertire questo per System.DirectoryServices.Protocols. Questa si è rivelata un vicolo cieco. Il modo in cui lo si fa in SDS.P e il modo in cui funziona il codice di esempio sono diversi abbastanza che è di alcun aiuto. Ecco la soluzione mi è venuta:

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

Si tratta di una classe relativamente semplice che è possibile utilizzare per registrare le ricerche. Il trucco sta usando il metodo GetPartialResults nel metodo di callback per ottenere solo il cambiamento che si è appena verificato. Ho anche incluso la classe EventArgs molto semplificato che sto usando per passare i risultati indietro. Nota, non sto facendo nulla di threading qui e non ho alcuna gestione degli errori (questo è solo un esempio). Si può consumare questa classe in questo modo:

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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top