Share via


Réception de notifications d’événements asynchrones

La notification d’événements asynchrone est une technique qui permet à une application de surveiller en permanence les événements sans monopoliser les ressources système. Les notifications d’événements asynchrones ont les mêmes limitations de sécurité que les autres appels asynchrones. Vous pouvez effectuer des appels semi-synchronisés à la place. Pour plus d’informations, consultez Appeler une méthode.

La file d’attente d’événements asynchrones acheminés vers un client a le potentiel de croître exceptionnellement. Par conséquent, WMI implémente une stratégie à l’échelle du système pour éviter de manquer de mémoire. WMI ralentit les événements ou commence à supprimer les événements de la file d’attente lorsque la file d’attente augmente au-delà d’une certaine taille.

WMI utilise les propriétés LowThresholdOnEvents et HighThresholdOnEvents de la classe Win32_WMISetting pour définir des limites d’évitement de mémoire insuffisante. La valeur minimale indique quand WMI doit commencer à ralentir la notification d’événement, et la valeur maximale indique quand commencer à supprimer les événements. Les valeurs par défaut pour les seuils bas et élevé sont 1000000 (10 Mo) et 2000000 (20 Mo). En outre, vous pouvez définir la propriété MaxWaitOnEvents pour décrire la durée pendant laquelle WMI doit attendre avant de supprimer les événements. La valeur par défaut pour MaxWaitOnEvents est 2000, soit 2 secondes.

Réception de notifications d’événements asynchrones dans VBScript

Les appels de script pour recevoir des notifications d’événements sont essentiellement les mêmes que tous les appels asynchrones présentant les mêmes problèmes de sécurité. Pour plus d’informations, consultez Effectuer un appel asynchrone avec VBScript.

Pour recevoir des notifications d’événements asynchrones dans VBScript

  1. Créez un objet récepteur en appelant WScript.CreateObject et en spécifiant le progid de « WbemScripting » et le type d’objet de SWbemSink. L’objet récepteur reçoit les notifications.

  2. Écrivez une sous-routine pour chaque événement que vous souhaitez gérer. Le tableau suivant répertorie les événements SWbemSink.

    Événement Signification
    OnObjectReady Signale les retours d’un objet au récepteur. L’utilisation de cet appel retourne un objet à chaque fois jusqu’à ce que l’opération soit terminée.
    OnCompleted Signale lorsqu’un appel asynchrone est terminé. Cet événement ne se produit jamais si l’opération est indéfinie.
    OnObjectPut Signale l’achèvement d’une opération de put asynchrone. Cet événement retourne le chemin d’objet de l’instance ou de la classe enregistrée.
    OnProgress Signale l’état d’un appel asynchrone en cours. Tous les fournisseurs ne prennent pas en charge les rapports d’avancement intermédiaires.
    Annuler Annule toutes les opérations asynchrones en suspens associées à ce récepteur d’objets.

     

L’exemple de code VBScript suivant avertit la suppression des processus avec un intervalle d’interrogation de 10 secondes. Dans ce script, la sous-routine SINK_OnObjectReady gère l’occurrence de l’événement. Dans l’exemple, l’objet récepteur est nommé « Sink », mais vous pouvez nommer cet objet comme vous le souhaitez.

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

Réception de notifications d’événements asynchrones dans C++

Pour effectuer une notification asynchrone, vous créez un thread distinct uniquement pour surveiller et recevoir des événements à partir de Windows Management Instrumentation (WMI). Lorsque ce thread reçoit un message, le thread avertit votre application principale.

En dédiant un thread distinct, vous autorisez votre processus principal à effectuer d’autres activités en attendant l’arrivée d’un événement. La remise asynchrone des notifications améliore les performances, mais peut offrir moins de sécurité que vous ne le souhaitez. Dans C++, vous avez la possibilité d’utiliser l’interface IWbemUnsecuredApartment ou d’effectuer des vérifications d’accès sur des descripteurs de sécurité. Pour plus d’informations, consultez Définition de la sécurité sur un appel asynchrone.

Pour configurer des notifications d’événements asynchrones

  1. Avant d’initialiser des notifications asynchrones, assurez-vous que vos paramètres d’évitement de mémoire insuffisante sont correctement définis dans Win32_WMISetting.

  2. Déterminez le type de bot que vous souhaitez générer.

    WMI prend en charge les événements intrinsèques et extrinsèques. Un événement intrinsèque est un événement prédéfini par WMI, tandis qu’un événement extrinsèque est un événement défini par un fournisseur tiers. Pour plus d’informations, consultez Détermination du type d’événement à recevoir.

La procédure suivante décrit comment recevoir des notifications d’événements asynchrones dans C++.

Pour recevoir des notifications d’événements asynchrones dans C++

  1. Configurez votre application avec des appels aux fonctions CoInitializeEx et CoInitializeSecurity.

    L’appel de CoInitializeEx initialise COM, tandis que CoInitializeSecurity accorde à WMI l’autorisation d’appeler le processus du consommateur. La fonction CoInitializeEx vous permet également de programmer une application multithread, ce qui est nécessaire pour la notification asynchrone. Pour plus d’informations, consultez Maintenance de la sécurité WMI.

    Le code de cette rubrique nécessite la compilation correcte des références et des instructions #include suivantes.

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

    L’exemple de code suivant explique comment configurer le consommateur d’événements temporaires avec des appels à CoInitializeEx et 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. Créez un objet récepteur via l’interface IWbemObjectSink.

    WMI utilise IWbemObjectSink pour envoyer des notifications d’événements et pour signaler l’état d’une opération asynchrone ou d’une notification d’événement.

  3. Inscrivez votre consommateur d’événements avec un appel à la méthode IWbemServices::ExecNotificationQueryAsync.

    Assurez-vous que le paramètre pResponseHandler pointe vers l’objet récepteur créé à l’étape précédente.

    L’objectif de l’inscription est de recevoir uniquement les notifications requises. La réception de notifications superflues gaspille le temps de traitement et de livraison, et n’utilise pas la capacité de filtrage de WMI au maximum du potentiel.

    Toutefois, un consommateur temporaire peut recevoir plusieurs types d’événements. Dans ce cas, un consommateur temporaire doit effectuer des appels distincts à IWbemServices::ExecNotificationQueryAsync pour chaque type d’événement. Par exemple, un consommateur peut exiger une notification lors de la création de nouveaux processus (événement de création d’instance ou __InstanceCreationEvent) et des modifications apportées à certaines clés de registre (événement de registre tel que RegistryKeyChangeEvent). Par conséquent, le consommateur effectue un appel à ExecNotificationQueryAsync pour s’inscrire aux événements de création instance et un autre appel à ExecNotificationQueryAsync pour s’inscrire aux événements du registre.

    Si vous choisissez de créer un consommateur d’événements qui s’inscrit pour plusieurs événements, vous devez éviter d’inscrire plusieurs classes avec le même récepteur. Utilisez plutôt un récepteur distinct pour chaque classe d’événement inscrit. Le fait d’avoir un récepteur dédié simplifie le traitement et facilite la maintenance, ce qui vous permet d’annuler une inscription sans affecter les autres.

  4. Effectuez toutes les activités nécessaires dans votre consommateur d’événements.

    Cette étape doit contenir la majeure partie de votre code et inclure des activités telles que l’affichage d’événements dans une interface utilisateur.

  5. Lorsque vous avez terminé, annulez l’inscription du consommateur d’événements temporaires avec un appel à l’événement IWbemServices::CancelAsyncCall.

    Que l’appel à CancelAsyncCall réussisse ou échoue, ne supprimez pas l’objet récepteur tant que le nombre de références d’objet n’a pas atteint zéro. Pour plus d’informations, consultez Appeler une méthode.