Ricezione di notifiche di eventi asincrone

La notifica degli eventi asincroni è una tecnica che consente a un'applicazione di monitorare costantemente gli eventi senza monopolizzare le risorse di sistema. Le notifiche degli eventi asincrone hanno le stesse limitazioni di sicurezza che hanno altre chiamate asincrone. È invece possibile effettuare chiamate semisynchronous. Per altre informazioni, vedere Chiamata di un metodo.

La coda di eventi asincroni indirizzati a un client ha il potenziale di aumentare notevolmente le dimensioni. Wmi implementa pertanto criteri a livello di sistema per evitare l'esaurimento della memoria. WMI rallenta gli eventi o avvia l'eliminazione di eventi dalla coda quando la coda supera una determinata dimensione.

WMI usa le proprietà LowThresholdOnEvents e HighThresholdOnEvents della classe Win32_WMISetting per impostare limiti per evitare la memoria insufficiente. Il valore minimo indica quando WMI deve iniziare a rallentare la notifica degli eventi e il valore massimo indica quando avviare l'eliminazione degli eventi. I valori predefiniti per le soglie basse e elevate sono 1000000 (10 MB) e 2000000 (20 MB). Inoltre, è possibile impostare la proprietà MaxWaitOnEvents per descrivere la quantità di tempo in cui WMI deve attendere prima di eliminare gli eventi. Il valore predefinito per MaxWaitOnEvents è 2000 o 2 secondi.

Ricezione di notifiche di eventi asincrone in VBScript

Le chiamate di scripting per ricevere le notifiche degli eventi sono essenzialmente identiche a tutte le chiamate asincrone con gli stessi problemi di sicurezza. Per altre informazioni, vedere Esecuzione di una chiamata asincrona con VBScript.

Per ricevere notifiche asincrone degli eventi in VBScript

  1. Creare un oggetto sink chiamando WScript.CreateObject e specificando il progid di "WbemScripting" e il tipo di oggetto di SWbemSink. L'oggetto sink riceve le notifiche.

  2. Scrivere una subroutine per ogni evento che si vuole gestire. Nella tabella seguente sono elencati gli eventi SWbemSink .

    Evento Significato
    OnObjectReady Segnala i ritorni di un oggetto al sink. L'utilizzo di questa chiamata restituisce un oggetto ogni volta fino al completamento dell'operazione.
    OnCompleted Segnala quando viene completata una chiamata asincrona. Questo evento non si verifica mai se l'operazione è indefinita.
    OnObjectPut Segnala il completamento di un'operazione put asincrona. Questo evento restituisce il percorso dell'oggetto dell'istanza o della classe salvata.
    OnProgress Segnala lo stato di una chiamata asincrona in corso. Non tutti i provider supportano report di stato provvisori.
    Annulla Annulla tutte le operazioni asincrone in sospeso associate a questo sink di oggetti.

     

Nell'esempio di codice VBScript seguente viene notificata l'eliminazione dei processi con un intervallo di polling di 10 secondi. In questo script la subroutine SINK_OnObjectReady gestisce l'occorrenza dell'evento. Nell'esempio, l'oggetto sink è denominato "Sink", ma è possibile denominare questo oggetto durante la scelta.

strComputer = "." 
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2") 
Set MySink = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK_")

objWMIservice.ExecNotificationQueryAsync MySink, _
    "SELECT * FROM __InstanceDeletionEvent" _
    & " WITHIN 10 WHERE TargetInstance ISA 'Win32_Process'"


WScript.Echo "Waiting for events..."

While (True)
    Wscript.Sleep(1000)
Wend

Sub SINK_OnObjectReady(objObject, objAsyncContext)
    Wscript.Echo "__InstanceDeletionEvent event has occurred."
End Sub

Sub SINK_OnCompleted(objObject, objAsyncContext)
    WScript.Echo "Event call complete."
End Sub

Ricezione di notifiche di eventi asincrone in C++

Per eseguire una notifica asincrona, creare un thread separato esclusivamente per monitorare e ricevere eventi da Strumentazione gestione Windows (WMI). Quando il thread riceve un messaggio, il thread invia una notifica all'applicazione principale.

Dedicando un thread separato, si consente al processo principale di eseguire altre attività durante l'attesa dell'arrivo di un evento. Il recapito asincrono delle notifiche migliora le prestazioni, ma può offrire una sicurezza inferiore a quella desiderata. In C++, è possibile usare l'interfaccia IWbemUnsecuredApartment o eseguire controlli di accesso sui descrittori di sicurezza. Per altre informazioni, vedere Impostazione della sicurezza in una chiamata asincrona.

Per configurare le notifiche degli eventi asincrone

  1. Prima di inizializzare le notifiche asincrone, assicurarsi che i parametri di prevenzione della memoria insufficiente siano impostati correttamente in Win32_WMISetting.

  2. Determinare il tipo di eventi che si desidera ricevere.

    WMI supporta eventi intrinseci ed estrini. Un evento intrinseco è un evento predefinito da WMI, mentre un evento estrinsico è un evento definito da un provider di terze parti. Per altre informazioni, vedere Determinazione del tipo di evento da ricevere.

La procedura seguente descrive come ricevere notifiche degli eventi asincrone in C++.

Per ricevere notifiche di eventi asincrone in C++

  1. Configurare l'applicazione con chiamate alle funzioni CoInitializeEx e CoInitializeSecurity .

    La chiamata a CoInitializeEx inizializza COM, mentre CoInitializeSecurity concede a WMI l'autorizzazione per chiamare nel processo del consumer. La funzione CoInitializeEx consente inoltre di programmare un'applicazione multithreading, necessaria per la notifica asincrona. Per altre informazioni, vedere Gestione della sicurezza WMI.

    Il codice in questo argomento richiede che i riferimenti e le istruzioni #include seguenti vengano compilati correttamente.

    #define _WIN32_DCOM
    #include <iostream>
    using namespace std;
    #include <wbemidl.h>
    

    L'esempio di codice seguente descrive come configurare il consumer di eventi temporanei con chiamate a CoInitializeEx e CoInitializeSecurity.

    void main(int argc, char **argv)
    {
        HRESULT hr = 0;
        hr = CoInitializeEx (0, COINIT_MULTITHREADED);
        hr = CoInitializeSecurity (NULL, 
           -1, 
           NULL, 
           NULL,   
           RPC_C_AUTHN_LEVEL_NONE, 
           RPC_C_IMP_LEVEL_IMPERSONATE, 
           NULL,
           EOAC_NONE,
           NULL); 
    
        if (FAILED(hr))
        {
           CoUninitialize();
           cout << "Failed to initialize security. Error code = 0x"
               << hex << hr << endl;
           return;
        }
    
    // ...
    }
    
  2. Creare un oggetto sink tramite l'interfaccia IWbemObjectSink .

    WMI usa IWbemObjectSink per inviare notifiche degli eventi e per segnalare lo stato su un'operazione asincrona o una notifica degli eventi.

  3. Registrare il consumer di eventi con una chiamata al metodo IWbemServices::ExecNotificationQueryAsync .

    Assicurarsi che il parametro pResponseHandler punti all'oggetto sink creato nel passaggio precedente.

    Lo scopo della registrazione è ricevere solo le notifiche necessarie. Ricezione di notifiche superflue rifiuti di lavorazione e tempo di consegna; e non usa la capacità di filtro di WMI al massimo potenziale.

    Tuttavia, un consumer temporaneo può ricevere più di un tipo di evento. In questo caso, un consumer temporaneo deve effettuare chiamate separate a IWbemServices::ExecNotificationQueryAsync per ogni tipo di evento. Ad esempio, un consumer potrebbe richiedere una notifica quando vengono creati nuovi processi (un evento di creazione dell'istanza o __InstanceCreationEvent) e per le modifiche apportate a determinate chiavi del Registro di sistema (un evento del Registro di sistema, ad esempio RegistryKeyChangeEvent). Di conseguenza, il consumer effettua una chiamata a ExecNotificationQueryAsync per registrare gli eventi di creazione di istanze e un'altra chiamata a ExecNotificationQueryAsync per la registrazione per gli eventi del Registro di sistema.

    Se si sceglie di creare un consumer di eventi che esegue la registrazione per più eventi, è consigliabile evitare di registrare più classi con lo stesso sink. Usare invece un sink separato per ogni classe di evento registrato. La presenza di un sink dedicato semplifica l'elaborazione e facilita la manutenzione, consentendo di annullare una registrazione senza influire sugli altri.

  4. Eseguire tutte le attività necessarie nel consumer di eventi.

    Questo passaggio deve contenere la maggior parte del codice e includere attività come la visualizzazione di eventi a un'interfaccia utente.

  5. Al termine, annullare la registrazione del consumer di eventi temporanei con una chiamata all'evento IWbemServices::CancelAsyncCall .

    Indipendentemente dal fatto che la chiamata a CancelAsyncCall abbia esito positivo o negativo, non eliminare l'oggetto sink finché il conteggio dei riferimenti all'oggetto non raggiunge lo zero. Per altre informazioni, vedere Chiamata di un metodo.