Pregunta

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

Puede registrar hasta cinco solicitudes de notificación sobre una sola conexión LDAP. Debe tener un hilo dedicado que espera a que las notificaciones y los procesa rápidamente. Cuando se llama a la función ldap_search_ext para registrar una solicitud de notificación, la función devuelve un identificador de mensaje que identifica a esa petición. A continuación, utiliza la función ldap_result que esperar a que las notificaciones de cambio. Cuando se produce un cambio, el servidor le envía un mensaje de LDAP que contiene el identificador de mensaje para la solicitud de notificación que generó la notificación. Esto hace que la función ldap_result para volver con los resultados de búsqueda que identifican el objeto que ha cambiado.

No puedo encontrar un comportamiento similar mirando a través de la documentación de .NET. Si alguien sabe cómo hacer esto en C # yo estaría muy agradecido de saber. Estoy mirando a ver cuando cambian los atributos de todos los usuarios en el sistema para que pueda realizar acciones personalizadas en función de lo que ha cambiado.

He mirado a través stackoverflow y otras fuentes sin suerte.

Gracias.

¿Fue útil?

Solución

No estoy seguro de que hace lo que necesita, pero echar un vistazo a http: // dunnry. com / blog / ImplementingChangeNotificationsInNET.aspx

Editar: Se añadió texto y el código del artículo:



Hay tres maneras de averiguar cosas que han cambiado en Active Directory (o ADAM). Estos se han documentado durante algún tiempo sobre al MSDN en el acertadamente titulado " Descripción general de seguimiento de cambios Técnicas" . En resumen:

  1. sondeo de cambios usando uSNChanged . Esta técnica comprueba el valor de 'highestCommittedUSN' para comenzar y luego realiza búsquedas de valores 'uSNChanged' que son más altos posteriormente. El atributo 'uSNChanged' no se replica entre controladores de dominio, por lo que debe volver al mismo controlador de dominio cada vez para mantener la coherencia. En esencia, se realiza una búsqueda en busca de la más alta valor 'uSNChanged' + 1 y luego lee en los resultados de seguimiento de los mismos en cualquier forma que desee.
    • Beneficios
      • Esta es la forma más compatible. Todas las lenguas y todas las versiones de .NET apoyan esta manera, ya que es una simple búsqueda.
    • Las desventajas
      • Hay mucho aquí por el desarrollador para cuidar. Usted consigue todo el objeto de vuelta, y debe determinar qué ha cambiado en el objeto (y si se preocupan por que el cambio).
      • Tratar con objetos borrados es un dolor.
      • Se trata de una técnica de sondeo, por lo que es como en tiempo real, con qué frecuencia se consulta. Esto puede ser una buena cosa dependiendo de la aplicación. Tenga en cuenta, los valores intermedios no se realiza un seguimiento aquí tampoco.
  2. sondeo de cambios con el de control de sincronización de directorios. Esta técnica utiliza la opción ADS_SEARCHPREF_DIRSYNC en ADSI y el control LDAP_SERVER_DIRSYNC_OID bajo las sábanas. Basta con hacer una búsqueda inicial, almacenar la cookie, y luego buscar de nuevo y enviar la cookie. Se devolverá sólo los objetos que han cambiado.
    • Beneficios
      • Este es un modelo fácil de seguir. Ambos System.DirectoryServices y System.DirectoryServices.Protocols soportan esta opción.
      • El filtrado puede reducir lo que tiene que molestarse con. A modo de ejemplo, si mi búsqueda inicial es para todos los usuarios "(objectClass = user)", que puede filtrar posteriormente el sondeo con "(sn = Dunn)" y sólo volver a la combinación de ambos filtros, en lugar de tener que lidiar con todo, desde el filtro intial.
      • opción de Windows 2003+ elimina la limitación administrativa para el uso de esta opción (la seguridad de objetos).
      • opción de Windows 2003+ también le dará la capacidad de devolver sólo los valores incrementales que han cambiado en grandes atributos de varios valores. Esta es una característica muy agradable.
      • Ofertas bien con los objetos eliminados.
    • Las desventajas
      • Este es .NET 2.0+ o temprano única opción. Los usuarios de .NET 1.1 tendrán que utilizar uSNChanged de seguimiento. Los lenguajes de script no puede utilizar este método.
      • Sólo puede alcance de la búsqueda a una partición. Si desea realizar un seguimiento de una única unidad organizativa o un objeto en particular, debe ordenar los resultados usted mismo más tarde.
      • El uso de este con dominios de modo de no-Windows 2003 viene con la restricción de que debe tener la replicación Obtener cambios permisos (por defecto sólo administrador) para su uso.
      • Se trata de una técnica de sondeo. No hace un seguimiento valores intermedios EITsu. Por lo tanto, si un objeto que desea realizar un seguimiento de los cambios entre las búsquedas en múltiples ocasiones, se le obtener sólo el último cambio. Esto puede ser una ventaja dependiendo de la aplicación.
  3. notificaciones de cambio de Directorio activo . Esta técnica registra una búsqueda en un hilo separado que recibirá notificaciones cuando cualquier cambio de objeto que coincide con el filtro. Puede registrar hasta 5 notificaciones por conexión asíncrona.
    • Beneficios
      • Notificación instantánea. Las otras técnicas requieren de votación.
      • Debido a que esta es una notificación, obtendrá todos los cambios, incluso los intermedios que se han perdido en las otras dos técnicas.
    • Las desventajas
      • Relativamente muchos recursos. Usted no quiere hacer una tonelada de éstos, ya que podría causar problemas de escalabilidad con su controlador.
      • Esto sólo le indica si el objeto ha cambiado, pero no le dice lo que fue el cambio. Es necesario averiguar si el atributo que se preocupan por ha cambiado o no. Dicho esto, es bastante fácil de saber si el objeto ha sido eliminado (más fácil que uSNChanged de votación por lo menos).
      • Sólo se puede hacer esto en código no administrado o con System.DirectoryServices.Protocols.

En su mayor parte, he encontrado que la sincronización de directorios tiene cumplía los requisitos para mí en casi todas las situaciones. Nunca se molestó en tratar cualquiera de las otras técnicas. Sin embargo, un lector preguntó si había una manera de hacer las notificaciones de cambio en .NET. Pensé que era posible utilizando SDS.P, pero nunca había probado. Resulta que es posible y de hecho no es demasiado difícil de hacer.

Mi primer pensamiento al escribir este era utilizar el código de ejemplo encontramos en MSDN ( y se hace referencia a la opción # 3) y convertirlo fácilmente en System.DirectoryServices.Protocols. Esto resultó ser un callejón sin salida. La forma en que lo hace en SDS.P y la forma en que funciona el ejemplo de código son lo suficientemente diferentes que no es de ayuda. Aquí está la solución que se me ocurrió:

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

Es una clase relativamente simple que se puede utilizar para registrar las búsquedas. El truco está utilizando el método GetPartialResults en el método de devolución de llamada para obtener sólo el cambio que acaba de ocurrir. También he incluido la clase EventArgs muy simplificado que estoy utilizando para transmitir los resultados de vuelta. Tenga en cuenta, no estoy haciendo nada de enhebrar aquí y no tengo ningún control de errores (esto es sólo una muestra). Usted puede consumir esta clase de esta manera:

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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top