Receber um evento do WMI

O WMI contém uma infraestrutura de eventos que produz notificações sobre alterações em dados e serviços do WMI. As classes de evento do WMI fornecem notificação quando ocorrem eventos específicos.

As seções a seguir serão abordadas neste tópico:

Consultas de eventos

Você pode criar uma consulta semissíncrona ou assíncrona para monitorar alterações em logs de eventos, criação de processos, status de serviço, disponibilidade do computador ou espaço livre da unidade de disco e outras entidades ou eventos. No script, o método SWbemServices.ExecNotificationQuery é usado para assinar eventos. IWbemServices::ExecNotificationQuery é usado em C++. Para obter mais informações, consulte Chamar um método.

A notificação de uma alteração no modelo de dados do WMI padrão é chamada de evento intrínseco. __InstanceCreationEvent ou __NamespaceDeletionEvent são exemplos de eventos intrínsecos. A notificação de uma alteração que um provedor faz para definir um evento de provedor é chamada de evento extrínseco. Por exemplo, o Provedor de registro do sistema, o Provedor de eventos de gerenciamento de energia e o Provedor Win32 definem seus próprios eventos. Para obter mais informações, consulte Determinar o tipo de evento a receber.

Exemplo

O exemplo de código de script a seguir é uma consulta ao __InstanceCreationEvent intrínseco da classe de evento Win32_NTLogEvent. Você pode executar esse programa em segundo plano e, quando houver um evento, uma mensagem será exibida. Se você fechar a caixa de diálogo Aguardando eventos, o programa deixará de aguardar eventos. Lembre-se de que SeSecurityPrivilege deve estar habilitado.

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    WScript.Echo (objObject.TargetInstance.Message)
End Sub

Set objWMIServices = GetObject( _
    "WinMgmts:{impersonationLevel=impersonate, (security)}") 

' Create the event sink object that receives the events
Set sink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
 
' Set up the event selection. SINK_OnObjectReady is called when
' a Win32_NTLogEvent event occurs
objWMIServices.ExecNotificationQueryAsync sink,"SELECT * FROM __InstanceCreationEvent " & "WHERE TargetInstance ISA 'Win32_NTLogEvent' "

WScript.Echo "Waiting for events"

# Define event Query
$query = "SELECT * FROM __InstanceCreationEvent 
          WHERE TargetInstance ISA 'Win32_NTLogEvent' "

<# Register for event - also specify an action that
displays the log event when the event fires.#>

Register-WmiEvent -Source Demo1 -Query $query -Action {
                Write-Host "Log Event occured"
                $global:myevent = $event
                Write-Host "EVENT MESSAGE"
                Write-Host $event.SourceEventArgs.NewEvent.TargetInstance.Message}
<# So wait #>
"Waiting for events"

O exemplo de código VBScript a seguir mostra o evento extrínseco __RegistryValueChangeEvent que o provedor do registro define. O script cria um consumidor temporário usando a chamada para SWbemServices.ExecNotificationQueryAsync e apenas recebe eventos quando o script está em execução. O script a seguir é executado indefinidamente até que o computador seja reinicializado, o WMI seja interrompido ou o script seja interrompido. Para interromper o script manualmente, use o Gerenciador de Tarefas e pare o processo. Para interrompê-lo programaticamente, use o método Terminate na classe Win32_Process. Para obter mais informações, consulte Configurar a segurança em uma chamada assíncrona.

strComputer = "."

Set objWMIServices=GetObject( _
    "winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default")

set objSink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")


objWMIServices.ExecNotificationQueryAsync objSink, _
    "Select * from RegistryValueChangeEvent Where Hive = 'HKEY_LOCAL_MACHINE' and KeyPath = 'SYSTEM\\ControlSet001\\Control' and ValueName = 'CurrentUser'"

WScript.Echo "Waiting for events..."

While (True) 
     WScript.Sleep (1000)
Wend

 
WScript.Echo "Listening for Registry Change Events..." & vbCrLf 

While(True) 
    WScript.Sleep 1000 
Wend 

Sub SINK_OnObjectReady(wmiObject, wmiAsyncContext) 
    WScript.Echo "Received Registry Value Change Event" & vbCrLf & wmiObject.GetObjectText_() 
End Sub

Consumidores de evento

Você pode monitorar ou consumir eventos usando os seguintes consumidores enquanto um script ou aplicativo está em execução:

  • Consumidores de evento temporários

    Um consumidor temporário é um aplicativo cliente do WMI que recebe um evento do WMI. O WMI inclui uma interface exclusiva usada para especificar os eventos para que o WMI envie para um aplicativo cliente. Um consumidor de evento temporário é considerado temporário porque só funciona quando carregado especificamente por um usuário. Para obter mais informações, consulte Receber eventos pela duração do seu aplicativo.

  • Consumidores de evento permanentes

    Um consumidor permanente é um objeto COM que pode receber um evento do WMI o tempo todo. Um consumidor de evento permanente usa um conjunto de objetos persistentes e filtros para capturar um evento do WMI. Como consumidor de evento temporário, você configura uma série de objetos e filtros do WMI que capturam um evento do WMI. Quando ocorre um evento que corresponde a um filtro, o WMI carrega o consumidor de evento permanente e o notifica sobre o evento. Como um consumidor permanente é implementado no repositório WMI e é um arquivo executável registrado no WMI, o consumidor de evento permanente opera e recebe eventos depois de ser criado e até mesmo após uma reinicialização do sistema operacional enquanto o WMI estiver em execução. Para obter mais informações, consulte Receber eventos sempre.

Scripts ou aplicativos que recebem eventos têm considerações de segurança especiais. Para obter mais informações, consulte Proteger eventos do WMI.

Um aplicativo ou script pode usar um provedor interno de evento do WMI que fornece classes de consumidor padrão. Cada classe de consumidor padrão responde a um evento com uma ação diferente enviando uma mensagem de email ou executando um script. Você não precisa escrever o código do provedor para usar uma classe de consumidor padrão a fim de criar um consumidor de evento permanente. Para obter mais informações, confira Monitoramento e resposta a eventos com consumidores padrão.

Fornecer eventos

Um provedor de eventos é um componente COM que envia um evento para o WMI. Você pode criar um provedor de eventos para enviar um evento em um aplicativo C++ ou C#. A maioria dos provedores de eventos gerencia um objeto para o WMI, por exemplo, um item de hardware ou aplicativo. Para obter mais informações, consulte Gravar um provedor de eventos.

Um evento cronometrado ou repetido é um evento que ocorre em um momento predeterminado.

O WMI oferece as seguintes maneiras de criar eventos cronometrados ou repetidos para seus aplicativos:

  • A infraestrutura de eventos padrão da Microsoft.
  • Uma classe de temporizador especializada.

Para obter mais informações, consulte Receber um evento cronometrado ou repetido. Ao gravar um provedor de eventos, considere as informações de segurança identificadas em Fornecer eventos com segurança.

É recomendável que as assinaturas de eventos permanentes sejam compiladas no namespace \root\subscription. Para obter mais informações, consulte Implementar assinaturas de evento permanentes entre namespaces.

Cotas de assinatura

A sondagem de eventos pode prejudicar o desempenho de provedores que dão suporte a consultas em grandes conjuntos de dados. Além disso, qualquer usuário que tenha acesso de leitura a um namespace com provedores dinâmicos pode executar um ataque de negação de serviço (DoS). O WMI mantém cotas para todos os usuários combinados e para cada consumidor de evento na instância única de __ArbitratorConfiguration localizada no namespace \root. Essas cotas são globais e não para cada namespace. Você não pode alterar as cotas.

Atualmente, o WMI impõe cotas usando as propriedades de __ArbitratorConfiguration. Cada cota tem uma versão por usuário e uma total que inclui todos os usuários combinados e não por namespace. A tabela a seguir lista as cotas que se aplicam às propriedades de __ArbitratorConfiguration.

Total/PerUser Quota
TemporarySubscriptionsTotal
TemporarySubscriptionsPerUser
10.000
1,000
PermanentSubscriptionsTotal
PermanentSubscriptionsPerUser
10.000
1,000
PollingInstructionsTotal
PollingInstructionsPerUser
10.000
1,000
PollingMemoryTotal
PollingMemoryPerUser
10.000.000 (0x989680) bytes
5.000.000 (0x4CB40) bytes

Um administrador ou um usuário com permissão FULL_WRITE no namespace pode modificar a instância singleton de __ArbitratorConfiguration. O WMI rastreia a cota por usuário.

Como usar o WMI