使用 VBScript 进行异步调用

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

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

\ HKEY_LOCAL_MACHINE软件\微软\WBEM\CIMOM\UnsecAppAccessControlDefault

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

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

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

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

注意

活动服务器页 (ASP) 作为脚本主机不支持异步调用。

 

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

使用 VBScript 进行异步调用

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

    Set Service = GetObject("Winmgmts:")
    
  2. 使用 CreateObject 或 (创建对象接收器,以便Windows脚本主机 2.0 仅) OBJECT 标记,并将事件属性设置为 TRUE

    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脚本主机 (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 安全性