Ricezione di un evento WMI

WMI contiene un'infrastruttura di eventi che genera notifiche sulle modifiche apportate ai dati e ai servizi WMI. Le classi di evento WMI forniscono una notifica quando si verificano eventi specifici.

In questo argomento vengono illustrate le sezioni seguenti:

Query di eventi

È possibile creare una query semisynchrono oasincrona per monitorare le modifiche apportate ai registri eventi, alla creazione di processi, allo stato del servizio, alla disponibilità del computer o all'unità disco e ad altre entità o eventi. Nello scripting, il metodo SWbemServices.ExecNotificationQuery viene usato per sottoscrivere gli eventi. In C++, viene usato IWbemServices::ExecNotificationQuery . Per altre informazioni, vedere Chiamata di un metodo.

La notifica di una modifica nel modello di dati WMI standard è detta evento intrinseco. __InstanceCreationEvent o __NamespaceDeletionEvent sono esempi di eventi intrinseci. La notifica di una modifica apportata da un provider per definire un evento del provider è detta evento estrinsico. Ad esempio, il provider del Registro di sistema, il provider di eventi di risparmio energia e il provider Win32 definiscono i propri eventi. Per altre informazioni, vedere Determinazione del tipo di evento da ricevere.

Esempio

L'esempio di codice di script seguente è una query per il __InstanceCreationEvent intrinseco della classe di evento Win32_NTLogEvent. È possibile eseguire questo programma in background e, quando si verifica un evento, viene visualizzato un messaggio. Se si chiude la finestra di dialogo Attesa eventi , il programma smette di attendere gli eventi. Tenere presente che è necessario abilitare SeSecurityPrivilege .

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"

Nell'esempio di codice VBScript seguente viene illustrato l'evento etrinsico __RegistryValueChangeEvent definito dal provider del Registro di sistema. Lo script crea un consumer temporaneo usando la chiamata a SWbemServices.ExecNotificationQueryAsync e riceve solo gli eventi quando lo script è in esecuzione. Lo script seguente viene eseguito per un periodo illimitato fino a quando il computer non viene riavviato, WMI viene arrestato o lo script viene arrestato. Per arrestare manualmente lo script, usare Gestione attività per arrestare il processo. Per arrestarla a livello di codice, usare il metodo Terminate nella classe Win32_Process. Per altre informazioni, vedere Impostazione della sicurezza in una chiamata asincrona.

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

consumer di eventi

È possibile monitorare o utilizzare eventi usando i consumer seguenti durante l'esecuzione di uno script o di un'applicazione:

  • Consumer di eventi temporanei

    Un consumer temporaneo è un'applicazione client WMI che riceve un evento WMI. WMI include un'interfaccia univoca che usa per specificare gli eventi per WMI da inviare a un'applicazione client. Un consumer di eventi temporanei viene considerato temporaneo perché funziona solo quando viene caricato in modo specifico da un utente. Per altre informazioni, vedere Ricezione di eventi per la durata dell'applicazione.

  • Consumer di eventi permanenti

    Un consumer permanente è un oggetto COM che può ricevere sempre un evento WMI. Un consumer di eventi permanente usa un set di oggetti persistenti e filtri per acquisire un evento WMI. Analogamente a un consumer di eventi temporanei, si configura una serie di oggetti WMI e filtri che acquisisce un evento WMI. Quando si verifica un evento che corrisponde a un filtro, WMI carica il consumer di eventi permanente e ne notifica l'evento. Poiché un consumer permanente viene implementato nel repository WMI ed è un file eseguibile registrato in WMI, il consumer di eventi permanenti opera e riceve gli eventi dopo la creazione e anche dopo un riavvio del sistema operativo purché WMI sia in esecuzione. Per altre informazioni, vedere Ricezione di eventi in qualsiasi momento.

Gli script o le applicazioni che ricevono eventi hanno particolari considerazioni sulla sicurezza. Per altre informazioni, vedere Protezione degli eventi WMI.

Un'applicazione o uno script può usare un provider di eventi WMI predefinito che fornisce classi consumer standard. Ogni classe consumer standard risponde a un evento con un'azione diversa inviando un messaggio di posta elettronica o eseguendo uno script. Non è necessario scrivere codice del provider per usare una classe consumer standard per creare un consumer di eventi permanente. Per altre informazioni, vedere Monitoraggio e risposta agli eventi con consumer standard.

Fornitura di eventi

Un provider di eventi è un componente COM che invia un evento a WMI. È possibile creare un provider di eventi per inviare un evento in un'applicazione C++ o C#. La maggior parte dei provider di eventi gestisce un oggetto per WMI, ad esempio un'applicazione o un elemento hardware. Per altre informazioni, vedere Scrittura di un provider di eventi.

Un evento timed o ripetuto è un evento che si verifica in un momento predeterminato.

WMI offre i modi seguenti per creare eventi temporali o ripetuti per le applicazioni:

  • Infrastruttura di eventi Microsoft standard.
  • Classe timer specializzata.

Per altre informazioni, vedere Ricezione di un evento timed o repeating. Quando si scrive un provider di eventi, prendere in considerazione le informazioni di sicurezza identificate in Fornire eventi in modo sicuro.

È consigliabile compilare sottoscrizioni di eventi permanenti nello spazio dei nomi \root\subscription. Per altre informazioni, vedere Implementazione di sottoscrizioni di eventi permanenti tra spazi dei nomi.

Quote di sottoscrizione

Il polling degli eventi può ridurre le prestazioni per i provider che supportano query su set di dati di grandi dimensioni. Inoltre, qualsiasi utente con accesso in lettura a uno spazio dei nomi con provider dinamici può eseguire un attacco Denial of Service (DoS). WMI mantiene le quote per tutti gli utenti combinati e per ogni consumer di eventi nella singola istanza di __ArbitratorConfiguration che si trova nello spazio dei nomi \root. Queste quote sono globali anziché per ogni spazio dei nomi. Non è possibile modificare le quote.

WMI applica attualmente le quote usando le proprietà di __ArbitratorConfiguration. Ogni quota ha un valore per utente e una versione totale che include tutti gli utenti combinati, non per spazio dei nomi. Nella tabella seguente sono elencate le quote applicabili alle proprietà __ArbitratorConfiguration .

Totale/PerUser Quota
TemporarySubscriptionsTotal
TemporarySubscriptionsPerUser
10,000
1.000
PermanenteSubscriptionsTotal
PermanenteSubscriptionsPerUser
10,000
1.000
PollingInstructionsTotal
PollingInstructionsPerUser
10,000
1.000
PollingMemoryTotal
PollingMemoryPerUser
10.000.000 byte (0x989680)
5.000.000 byte (0x4CB40)

Un amministratore o un utente con autorizzazione FULL_WRITE nello spazio dei nomi può modificare l'istanza singleton di __ArbitratorConfiguration. WMI tiene traccia della quota per utente.

Uso di WMI