Condividi tramite


Ricezione di notifiche di eventi asincrone

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

La coda di eventi asincroni indirizzati a un client può aumentare notevolmente. Di conseguenza, WMI implementa 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 utilizza le proprietà LowThresholdOnEvents e HighThresholdOnEvents della classe Win32_WMISetting per impostare limiti per prevenire condizioni di esaurimento della memoria. 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 uguali a tutte le chiamate asincrone con gli stessi problemi di sicurezza. Per altre informazioni, vedere Effettuare una chiamata asincrona con VBScript.

Per ricevere notifiche di eventi asincrone 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 la restituzione di un oggetto al sink. L'utilizzo di questa chiamata restituisce un oggetto ogni volta fino a quando l'operazione è completata.
    OnCompleted Segnala quando viene completata una chiamata asincrona. Questo evento non si verifica mai se l'operazione è illimitata.
    OnObjectPut Segnala il completamento di un'operazione di inserimento asincrona. Questo evento restituisce il percorso dell'oggetto dell'istanza o della classe salvata.
    InProgresso Segnala lo stato di una chiamata asincrona in corso. Non tutti i provider supportano rapporti di avanzamento intermedio.
    Annulla Annulla tutte le operazioni asincrone attualmente in sospeso associate al sink dell'oggetto.

     

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 come si sceglie.

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 dalla Strumentazione di 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'interfacciaIWbemUnsecuredApartment 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 Determinare il tipo di evento da ricevere.

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

Per ricevere notifiche di eventi asincrone in C++

  1. Configurare la tua applicazione con chiamate alle funzioni CoInitializeEx e CoInitializeSecurity.

    Chiamando CoInitializeEx inizializza COM, mentre CoInitializeSecurity concede a WMI l'autorizzazione a chiamare all'interno del processo dell'utente. 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>
    

    Nell'esempio di codice seguente viene descritto come configurare il consumatore temporaneo di eventi 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. Registra il consumatore 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. Il ricevere notifiche superflue spreca tempo di elaborazione e consegna, e non utilizza al massimo il potenziale di filtro di WMI.

    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 a determinate chiavi del Registro di sistema (un evento del Registro di sistema, ad esempio RegistryKeyChangeEvent). Pertanto, 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 scegli di creare un consumatore di eventi che si registra per più eventi, è consigliabile evitare di registrare più classi con lo stesso sink. Invece, si consiglia di usare un lavello separato per ogni classe di evento registrato. La presenza di un ricevitore dedicato semplifica l'elaborazione e facilita la manutenzione, consentendo di annullare un'istanza di registrazione senza compromettere le altre.

  4. Esegui tutte le attività necessarie nel consumatore 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 ulteriori informazioni, vedere Chiamare un metodo.