Appel asynchrone en VBScript

L’exécution d’un appel asynchrone à une méthode WMI ou une méthode de fournisseur permet à un script de continuer à s’exécuter pendant que les objets sont retournés à un objet SWbemSink, et sont gérés par des méthodes telles que SWbemSink.OnObjectReady. Toutefois, les appels asynchrones ne sont pas recommandés, car les données ne sont peut-être pas retournées au même niveau de sécurité que celui de l’appel.

Quand vous utilisez des appels de récepteur asynchrones, par exemple SWbemSink.OnObjectReady pour obtenir les données retournées, vous pouvez définir la valeur de Registre suivante.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault

La définition de cette valeur de Registre garantit l’authentification des objets de données retournés au récepteur. Si UnsecAppAccessControlDefault a la valeur un (1), WMI effectue une vérification d’accès du retour des données. Les vérifications d’accès permettent de vérifier que les données proviennent de la source appropriée. Pour plus d’informations, consultez Définition de la sécurité sur un appel asynchrone.

Les méthodes asynchrones dont les noms finissent par « Async_ » sont toujours retournées immédiatement après avoir été appelées pour qu’un programme puisse continuer à s’exécuter. Par exemple, SWbemServices.ExecQuery est synchrone et bloque l’exécution jusqu’à ce que tous les objets soient retournés. La méthode SWbemServices.ExecQueryAsync est la version asynchrone non bloquante. Il existe un moyen plus sécurisé de rendre l’appel à SWbemServices.ExecQuery non bloquant. Il consiste à effectuer l’appel de manière semi-synchrone. Pour plus d’informations, consultez Définition de la sécurité sur un appel asynchrone et Exécution d’un appel semi-synchrone avec VBScript.

Le paramètre iFlags des appels asynchrones a toujours la valeur par défaut zéro (0). Les méthodes asynchrones ne fournissent pas de collection SWbemObjectSet à la sous-routine de récepteur. À la place, la sous-routine d’événement SWbemSink.OnObjectReady de votre script ou de votre application reçoit chaque objet en l’état.

Une fois l’appel asynchrone d’origine effectué, l’événement SWbemSink.OnCompleted du récepteur d’objets est appelé, puis le code que vous y placez est exécuté pour traiter le résultat de l’appel.

Notes

Une page ASP (Active Server Page) en tant qu’hôte de script ne prend pas en charge un appel asynchrone.

 

La procédure suivante explique comment effectuer un appel asynchrone en VBScript.

Pour effectuer un appel asynchrone en VBScript

  1. Connectez-vous à WMI pour obtenir un objet SWbemServices.

    Set Service = GetObject("Winmgmts:")
    
  2. Créez le récepteur d’objets en utilisant CreateObject ou, pour l’environnement d’exécution de scripts WSH (Windows Script Host) 2.0 uniquement, la balise OBJECT avec un attribut d’événements ayant la valeur TRUE.

    Set sink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
    

    -ou-

    <OBJECT progid="WbemScripting.SWbemSink" ID="SINK" events="true"/>
    
  3. Créez une sous-routine pour chaque événement qu’un événement asynchrone peut déclencher. Ces événements sont définis en tant que méthodes sur SWbemObject. Par exemple, WMI rappelle SWbemSink.OnObjectReady au retour de chaque instance.

    Quand vous créez la sous-routine, placez du code dans celle-ci pour gérer chaque événement au moment de sa réception.

    Sub SINK_OnCompleted(
          iHResult, 
          objErrorObject, 
          objAsyncContext
          )
        WScript.Echo "Asynchronous operation is done."
    End Sub
    
    Sub SINK_OnObjectReady(objObject, objAsyncContext)
        WScript.Echo (objObject.Name)
    End Sub
    

    Examinez le paramètre iHresult retourné par l’événement OnCompleted pour déterminer si l’appel asynchrone a réussi ou non, ou si une erreur s’est produite. En cas de réussite, la valeur passée dans le paramètre iHresult est égale à zéro (0). Toute autre valeur peut indiquer une erreur. Vous devez vérifier les valeurs de l’objet d’erreur retourné dans le paramètre objErrorObject.

  4. Effectuez un appel asynchrone, puis passez le nom de votre récepteur dans le paramètre objWbemSink.

    Service.InstancesOfAsync sink, "Win32_process"
    
  5. Effectuez un appel qui empêche le script de prendre fin avant la réception de tous les événements. Si votre script peut s’exécuter avec une interface d’écran, il existe une méthode simple qui consiste à utiliser une commande de l’environnement d’exécution de scripts WSH (Windows Script Host), Echo, comme le montre l’exemple suivant.

    WScript.Echo "Waiting for instances."
    

    Quand vous exécutez ce script, vous pouvez voir la première instance être retournée avant le message En attente d’instances, ou bien après. Il s’agit de la nature du traitement asynchrone. Si vous fermez la boîte de dialogue En attente d’instances trop tôt, vous ne verrez peut-être pas toutes les instances.

  6. Si les résultats de plusieurs appels asynchrones distincts sont retournés au même récepteur, stockez les données de distinction nécessaires dans le paramètre de contexte objWbemAsyncContext.

  7. Une fois que vous en avez fini avec le récepteur, annulez votre appel asynchrone avec la méthode Cancel.

    objwbemsink.Cancel()
    

    La méthode Cancel indique à WSH d’annuler tous les appels asynchrones associés à un objet de récepteur donné. Ainsi, vous pouvez utiliser des récepteurs distincts pour les opérations asynchrones qui doivent être indépendantes.

  8. Libérez l’objet de récepteur en lui affectant Nothing.

    set objwbemsink= Nothing
    

L’exemple de code suivant montre une requête asynchrone pour toutes les instances de Win32_Process sur la machine locale. Pour une version semi-synchrone de la même méthode, consultez Appel d’une méthode.

' Create an object sink
set oSink = WScript.CreateObject("wbemscripting.swbemsink","sink_")
' Connect to WMI and the cimv2 namespace, and obtain
' an SWbemServices object
set oSvc = GetObject("winmgmts:root\cimv2")

bdone = false
' Query for all Win32_Process objects
osvc.ExecQueryAsync oSink, "SELECT Name FROM Win32_Process"
' Wait until all instances are returned. 
' The bdone flag prevents the script from exiting until
' the sink.OnCompleted subroutine is executed when
' all the objects are returned.
while not bdone    
    wscript.sleep 1000
wend

' The sink subroutine to handle the OnObjectReady 
' event. This is called as each object returns.
sub sink_OnObjectReady(oInst, octx)
    WScript.Echo "Got Instance: " & oInst.Name
end sub
' The sink subroutine to handle the OnCompleted event.
' This is called when all the objects are returned. 
' The oErr parameter obtains an SWbemLastError object,
' if available from the provider.
sub sink_OnCompleted(HResult, oErr, oCtx)
    WScript.Echo "ExecQueryAsync completed"
    bdone = true
end sub

Appel d’une méthode

Maintenance de la sécurité WMI