Realización de una llamada asincrónica con VBScript

Realizar una llamada asincrónica a un método de WMI o a un método de proveedor permite que un script continúe ejecutándose mientras los objetos vuelven a un objeto SWbemSink y se controlan mediante métodos como SWbemSink.OnObjectReady. Sin embargo, no se recomiendan las llamadas asincrónicas porque es posible que los datos no se devuelvan en el mismo nivel de seguridad con el que se efectuó la llamada.

Al usar llamadas de receptor asincrónicas como SWbemSink.OnObjectReady para obtener datos devueltos, puede establecer el siguiente valor del registro.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault

Establecer este valor del registro garantiza la autenticación de los objetos de datos devueltos al receptor. Si UnsecAppAccessControlDefault se establece en uno (1), WMI realiza la comprobación de acceso de la devolución de datos. Las comprobaciones de acceso comprueban que los datos proceden del origen correcto. Para más información, consulte Establecimiento de la seguridad en una llamada asincrónica.

Los métodos asincrónicos con nombres que terminan en "Async_" siempre devuelven los objetos inmediatamente después de llamarlos para que un programa pueda continuar ejecutándose. Por ejemplo, SWbemServices.ExecQuery es sincrónico y bloquea la ejecución hasta que todos los objetos se han devuelto. El método SWbemServices.ExecQueryAsync es la versión asincrónica sin bloqueo. Una manera más segura de realizar la llamada a SWbemServices.ExecQuery sin bloqueo es realizar la llamada de forma semisincrónica. Para más información, consulte Establecimiento de la seguridad en una llamada asincrónica y Realización de una llamada semisincrónica con VBScript.

El parámetro iFlags para llamadas asincrónicas siempre tiene como valor predeterminado cero (0). Los métodos asincrónicos no proporcionan una colección de SWbemObjectSet a la subrutina receptora. En su lugar, la subrutina de eventos SWbemSink.OnObjectReady del script o la aplicación recibe cada objeto tal y como se proporciona.

Cuando se completa la llamada asincrónica original, llama al evento SWbemSink.OnCompleted del receptor del objeto y ejecuta el código que se coloca allí para procesar el resultado de la llamada.

Nota

Una página de Active Server (ASP) como host de script no admite una llamada asincrónica.

 

En el procedimiento siguiente se describe cómo realizar una llamada asincrónica mediante VBScript.

Para realizar una llamada asincrónica mediante VBScript

  1. Conéctese a WMI y obtenga un objeto SWbemServices.

    Set Service = GetObject("Winmgmts:")
    
  2. Cree el receptor de objetos mediante CreateObject o (solo para Windows Script Host 2.0) la etiqueta OBJECT con un atributo events establecido en TRUE.

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

    O bien

    <OBJECT progid="WbemScripting.SWbemSink" ID="SINK" events="true"/>
    
  3. Cree una subrutina para cada evento que un evento asincrónico pueda desencadenar. Estos eventos se definen como métodos en SWbemObject. Por ejemplo, WMI realiza una devolución de llamada a SWbemSink.OnObjectReady a medida que devuelve cada instancia.

    Al crear la subrutina, coloque el código en la subrutina para controlar cada evento cuando se reciba.

    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
    

    Examine el parámetro iHresult devuelto por el evento OnCompleted para determinar si la llamada asincrónica es correcta o no, o si se produjo un error. Si es correcta, el valor pasado en el parámetro iHresult es igual a cero (0). Cualquier otro valor puede indicar un error y debe comprobar los valores del objeto de error que se devuelve en el parámetro objErrorObject.

  4. Realice una llamada asincrónica y pase el nombre del receptor en el parámetro objWbemSink.

    Service.InstancesOfAsync sink, "Win32_process"
    
  5. Realice una llamada que impida que el script finalice antes de que se reciban todos los eventos. Si el script se puede ejecutar con una interfaz de pantalla, una manera sencilla de hacerlo es usar el comando Echo de Windows Script Host (WSH) que aparece en el ejemplo siguiente.

    WScript.Echo "Waiting for instances."
    

    Cuando ejecuta este script, es posible que vea que la primera instancia se devuelve antes del mensaje Esperando instancias o puede que aparezca después. Esta es la naturaleza del procesamiento asincrónico. Si cierra el cuadro de mensaje Esperando instancias demasiado pronto, puede que no vea todas las instancias.

  6. Si tiene resultados de varias llamadas asincrónicas diferentes que vuelven al mismo receptor, almacene los datos distintivos necesarios en el parámetro de contexto objWbemAsyncContext.

  7. Cuando termine con el receptor, cancele la llamada asincrónica con el método Cancel.

    objwbemsink.Cancel()
    

    El método Cancel indica a WSH que cancele todas las llamadas asincrónicas asociadas a un objeto receptor determinado. Por lo tanto, puede que desee usar receptores independientes para las operaciones asincrónicas que deben ser independientes.

  8. Libere el objeto receptor asignando el objeto receptor a Nothing.

    set objwbemsink= Nothing
    

En el ejemplo de código siguiente se muestra una consulta asincrónica de todas las instancias de Win32_Process en la máquina local. Para obtener una versión semisincrónica del mismo método, consulte Llamar a un método.

' 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

Llamar a un método

Mantenimiento de la seguridad de WMI