使用 VBScript 进行异步调用

WMI 方法提供程序方法进行异步调用允许脚本在对象返回到 SWbemSink 对象时继续执行,并由 SWbemSink.OnObjectReady 等方法处理。 但是,不建议使用异步调用,返回的数据可能与调用的安全级别不同。

使用 SWbemSink.OnObjectReady 等异步接收器调用获取返回的数据时,可以设置以下注册表值。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault

设置此注册表值可确保对返回到接收器的数据对象进行身份验证。 如果将“UnsecAppAccessControlDefault”设置为一 (1),则 WMI 对返回的数据执行访问检查。 访问检查验证数据是否来自正确的源。 有关详细信息,请参阅设置异步调用的安全性

名称以“Async_”结尾的异步方法始终在调用后立即返回,以便程序可以继续执行。 例如,SWbemServices.ExecQuery 是同步方法,并阻止执行,直到返回所有对象。 SWbemServices.ExecQueryAsync 是非阻止异步方法。 较安全地对 SWbemServices.ExecQuery 进行非阻止调用的方法是半同步调用。 有关详细信息,请参阅设置异步调用的安全性使用 VBScript 进行半同步调用

异步调用的“iFlags”参数始终默认为零 (0) 。 异步方法不向接收器子例程提供 SWbemObjectSet 集合。 相反,脚本或应用程序中的 SWbemSink.OnObjectReady 事件子例程会接收提供的每个对象。

原始异步调用完成后,它会调用对象接收器的 SWbemSink.OnCompleted 事件,并执行放置在其中的代码来处理调用结果。

注意

作为脚本主机的 Active Server Page (ASP) 不支持异步调用。

 

以下过程介绍如何使用 VBScript 进行异步调用。

使用 VBScript 进行异步调用

  1. 连接到 WMI 并获取 SWbemServices 对象。

    Set Service = GetObject("Winmgmts:")
    
  2. 使用 CreateObject 或事件属性设置为“TRUE”的 OBJECT 标记(仅限 Windows Script Host 2.0)。

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

    -或-

    <OBJECT progid="WbemScripting.SWbemSink" ID="SINK" events="true"/>
    
  3. 为异步事件可以触发的每个事件创建子例程。 这些事件定义为 SWbemObject 上的方法。 例如,WMI 在返回每个实例时对 SWbemSink.OnObjectReady 进行回拨。

    创建子例程时,请将代码放在子例程中,以便在收到每个事件时对其进行处理。

    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
    

    检查 OnCompleted 事件返回的“iHresult”参数,以确定异步调用是否成功,或者是否发生错误。 如果成功,则“iHresult”参数中传递的值等于零 (0)。 任何其他值都可能指示错误,应检查“objErrorObject”参数中返回的错误对象中的值。

  4. 进行异步调用,并在“objWbemSink”参数中传递接收器的名称。

    Service.InstancesOfAsync sink, "Win32_process"
    
  5. 进行调用,以防止脚本在接收所有事件之前结束。 如果可以使用屏幕界面运行脚本,则执行此操作的简单方法是使用 Windows Script Host (WSH) Echo 命令,如以下示例所示。

    WScript.Echo "Waiting for instances."
    

    执行此脚本时,可能会在“正在等待实例”消息之前看到第一个实例返回,也可能在之后。 这是异步处理的性质。 如果过早关闭“正在等待实例”消息框,则可能看不到所有实例。

  6. 如果有多个不同异步调用的结果返回到同一接收器,请将任何必要的区分数据存储在“objWbemAsyncContext”上下文参数中。

  7. 完成接收后,使用 Cancel 方法取消异步调用。

    objwbemsink.Cancel()
    

    Cancel 方法指示 WSH 取消与给定接收器对象关联的所有异步调用。 因此,可能需要对必须独立的异步操作使用单独的接收器。

  8. 通过将接收器对象分配给 Nothing 来释放接收器对象。

    set objwbemsink= Nothing
    

以下代码示例演示对本地计算机上所有 Win32_Process 实例的异步查询。 有关同一方法的半同步版本,请参阅调用方法

' 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

调用方法

维护 WMI 安全性