Pergunta

Esse link http://msdn.microsoft.com/en-us/library/aa772153(vs.85).aspx diz:

Você pode registrar até cinco solicitações de notificação em uma única conexão LDAP. Você deve ter um tópico dedicado que aguarde as notificações e os processa rapidamente. Quando você chama a função ldap_search_ext para registrar uma solicitação de notificação, a função retorna um identificador de mensagem que identifica essa solicitação. Em seguida, você usa a função LDAP_RESULT para aguardar notificações de alteração. Quando ocorre uma alteração, o servidor envia uma mensagem LDAP que contém o identificador de mensagem para a solicitação de notificação que gerou a notificação. Isso faz com que a função LDAP_RESULT retorne com os resultados da pesquisa que identificam o objeto que alterou.

Não consigo encontrar um comportamento semelhante olhando para a documentação do .NET. Se alguém souber como fazer isso em C#, ficaria muito grato por saber. Estou procurando ver quando os atributos mudam em todos os usuários do sistema para que eu possa executar ações personalizadas, dependendo do que mudou.

Eu olhei através do StackOverflow e outras fontes sem sorte.

Obrigado.

Foi útil?

Solução

Não tenho certeza se faz o que você precisa, mas dê uma olhada http://dunnry.com/blog/implementingchangenotificationsinnet.aspx

Editar: Texto e código adicionados do artigo:



Existem três maneiras de descobrir coisas que mudaram no Active Directory (ou Adam). Estes foram documentados há algum tempo no MSDN no apropriadamente intitulado "Visão geral das técnicas de rastreamento de mudanças ". Resumindo:

  1. Pesquisa para mudanças usando USNCHANGED. Essa técnica verifica o valor 'HighestCommitdusn' para iniciar e, em seguida, executa pesquisas por valores 'USNCHANGED' que são mais altos posteriormente. O atributo 'Usnchanged' não é replicado entre os controladores de domínio; portanto, você deve voltar ao mesmo controlador de domínio a cada vez em busca de consistência. Essencialmente, você realiza uma pesquisa procurando o valor mais alto 'Usnchanged' + 1 e depois lê os resultados que os rastreiam da maneira que desejar.
    • Benefícios
      • Esta é a maneira mais compatível. Todos os idiomas e todas as versões do .NET suportam dessa maneira, pois é uma pesquisa simples.
    • Desvantagens
      • Há muito aqui para o desenvolvedor cuidar. Você recupera o objeto inteiro e deve determinar o que mudou no objeto (e se você se preocupa com essa alteração).
      • Lidar com objetos excluídos é uma dor.
      • Esta é uma técnica de votação, por isso é apenas em tempo real como a frequência você consulta. Isso pode ser uma coisa boa, dependendo do aplicativo. Observe que os valores intermediários também não são rastreados aqui.
  2. Pesquisa para mudanças usando o controle Dirsync. Esta técnica usa a opção ADS_SEARCHPREF_DIRSYNC no ADSI e o controle LDAP_SERVER_DIRSYNC_OID nas tampas. Basta fazer uma pesquisa inicial, armazenar o cookie e, em seguida, pesquisar posteriormente e envie o cookie. Ele retornará apenas os objetos que mudaram.
    • Benefícios
      • Este é um modelo fácil de seguir. Ambos System.DirectoryServices e System.DirectoryServices.Protocols suportam esta opção.
      • A filtragem pode reduzir o que você precisa se preocupar. Como exemplo, se minha pesquisa inicial é para todos os usuários "(objectClass = user)", posso posteriormente filtrar a pesquisa com "(sn = dunn)" e apenas recuperar a combinação de ambos os filtros, em vez de ter que lidar com tudo, desde o filtro íntimo.
      • A opção Windows 2003+ remove a limitação administrativa para usar esta opção (segurança do objeto).
      • A opção Windows 2003+ também fornecerá a capacidade de retornar apenas os valores incrementais que mudaram em grandes atributos com vários valores. Este é um recurso muito bom.
      • Lida bem com objetos excluídos.
    • Desvantagens
      • Esta é a opção .NET 2.0+ ou posterior. Os usuários do .NET 1.1 precisarão usar o rastreamento USNCHANGED. Os idiomas de script não podem usar esse método.
      • Você só pode procurar a pesquisa para uma partição. Se você deseja rastrear apenas uma OU ou objeto específico, deve resolver esses resultados mais tarde.
      • Usando isso com os domínios do modo não Windows 2003 vem com a restrição de que você deve ter replicação obtendo permissões de alterações (somente padrão do Admin) a ser usado.
      • Esta é uma técnica de votação. Ele também não rastreia valores intermediários. Portanto, se um objeto que você deseja rastrear entre as pesquisas várias vezes, você obterá apenas a última alteração. Isso pode ser uma vantagem, dependendo do aplicativo.
  3. Alterar notificações no Active Directory. Essa técnica registra uma pesquisa em um encadeamento separado que receberá notificações quando qualquer objeto altera que corresponda ao filtro. Você pode registrar até 5 notificações por conexão assíncrona.
    • Benefícios
      • Notificação instantânea. As outras técnicas requerem pesquisas.
      • Por ser uma notificação, você receberá todas as alterações, mesmo as intermediárias que teriam sido perdidas nas outras duas técnicas.
    • Desvantagens
      • Relativamente intensivo em recursos. Você não quer fazer uma tonelada inteira, pois isso pode causar problemas de escalabilidade com seu controlador.
      • Isso só diz se o objeto mudou, mas não diz qual foi a mudança. Você precisa descobrir se o atributo com o qual você se preocupa mudou ou não. Dito isto, é muito fácil dizer se o objeto foi excluído (mais fácil do que a pesquisa de Usnchanged, pelo menos).
      • Você só pode fazer isso no código não gerenciado ou com o System.DirectoryServices.protocols.

Na maioria das vezes, descobri que a Dirsync se encaixou na conta de mim em praticamente todas as situações. Nunca me preocupei em experimentar nenhuma das outras técnicas. No entanto, um leitor perguntou se havia uma maneira de fazer as notificações de mudança no .NET. Imaginei que era possível usar o SDS.P, mas nunca o havia experimentado. Acontece que é possível e, na verdade, não é muito difícil de fazer.

Meu primeiro pensamento sobre escrever isso foi usar o Código de amostra encontrado no msdn (e referenciado na opção nº 3) e simplesmente convertê -lo em System.DirectoryServices.protocols. Acabou sendo um beco sem saída. A maneira como você faz isso no SDS.P e a maneira como o código de amostra funciona é diferente o suficiente para não ajudar. Aqui está a solução que eu criei:

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

É uma classe relativamente simples que você pode usar para registrar pesquisas. O truque é usar o método getPartialResults no método de retorno de chamada para obter apenas a alteração que acabou de ocorrer. Também incluí a classe EventArgs muito simplificada que estou usando para repassar os resultados de volta. Observe que eu não estou fazendo nada sobre rosquear aqui e não tenho nenhum erro de manuseio (este é apenas uma amostra). Você pode consumir esta aula como assim:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top