Making an Asynchronous Call with VBScript
Making an asynchronous call to a WMI method or a provider method allows a script to continue executing while objects return to an SWbemSink object, and are handled by methods such as SWbemSink.OnObjectReady. However, asynchronous calls are not recommended because the data may not be returned at the same level of security as the call is made.
When using asynchronous sink calls like SWbemSink.OnObjectReady to get returned data, you can set the following registry value.
Setting this registry value ensures authentication of the data objects returned to the sink. If UnsecAppAccessControlDefault is set to one (1), then WMI performs access checking of the data return. Access checks verify that the data comes from the correct source. For more information, see Setting Security on an Asynchronous Call.
Asynchronous methods with names that end in "Async_" always return immediately after being called so that a program can continue executing. For example, SWbemServices.ExecQuery is synchronous and blocks execution until all of the objects are returned. The SWbemServices.ExecQueryAsync method is the nonblocking asynchronous version. A more secure way to make the call to SWbemServices.ExecQuery nonblocking is by making the call semisynchronously. For more information, see Setting Security on an Asynchronous Call and Making a Semisynchronous Call with VBScript.
The iFlags parameter for asynchronous calls always defaults to zero (0). Asynchronous methods do not supply an SWbemObjectSet collection to the sink subroutine. Instead, the SWbemSink.OnObjectReady event subroutine in your script or application receives each object as it is provided.
When the original asynchronous call is complete, it calls the SWbemSink.OnCompleted event of the object sink, and executes the code you place there to process the result of the call.
An Active Server Page (ASP) as a script host does not support an asynchronous call.
The following procedure describes how to make an asynchronous call by using VBScript.
To make an asynchronous call using VBScript
Connect to WMI and get an SWbemServices object.
Set Service = GetObject("Winmgmts:")
Create the object sink using either CreateObject or (for Windows Script Host 2.0 only) the OBJECT tag with an events attribute set to TRUE.
Set sink = WScript.CreateObject("WbemScripting.SWbemSink","SINK_")
<OBJECT progid="WbemScripting.SWbemSink" ID="SINK" events="true"/>
Create a subroutine for each event an asynchronous event can trigger. These events are defined as methods on SWbemObject. For example, WMI makes a callback to SWbemSink.OnObjectReady as each instance returns.
When you create the subroutine, place code in the subroutine to handle each event when it is received.
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 the iHresult parameter returned by the OnCompleted event to determine whether or not the asynchronous call is successful, or if an error occurred. If successful, the value passed in the iHresult parameter is equal to zero (0). Any other value may indicate an error, and you should check the values in the error object that is returned in the objErrorObject parameter.
Make an asynchronous call and pass the name of your sink in the objWbemSink parameter.
Service.InstancesOfAsync sink, "Win32_process"
Make a call that prevents the script from ending before all of the events are received. If your script can run with a screen interface, a simple way to do this is to use a Windows Script Host (WSH)
Echocommand, which is shown in the following example.
WScript.Echo "Waiting for instances."
When you execute this script you may see the first instance return before the Waiting for instances message or you may see it after. This is the nature of asynchronous processing. If you close the Waiting for instances message box too soon, you may not see all of the instances.
If you have results from several different asynchronous calls returning to the same sink, store any necessary distinguishing data in the objWbemAsyncContext context parameter.
When finished with the sink, cancel your asynchronous call with the Cancel method.
The Cancel method instructs WSH to cancel all of the asynchronous calls associated with a given sink object. Thus, you may want to use separate sinks for asynchronous operations that must be independent.
Release the sink object by assigning the sink object to
set objwbemsink= Nothing
The following code example shows an asynchronous query for all the instances of Win32_Process on the local machine. For a semisynchronous version of the same method, see Calling a Method.
' 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