COM sample Vuser scripts
Caution: This protocol is supported for replay only. Support for this protocol will be discontinued in future versions.
This section shows examples of how VuGen emulates a COM client application. It is divided up into the basic COM script operations. Each type of operation is done within a separate scope.
To use a COM object, the application must first instantiate it and get a pointer to an interface of that object.
-
VuGen calls lrc_GUID to get a unique ProgID for the object, to be stored in pClsid:
GUID pClsid = lrc_GUID("student..1");
-
If the unknown interface pointer is a pointer to an aggregated object, VuGen retrieves the pointer to that object, or else it sets it to NULL:
IUnknown * pUnkOuter = (IUnknown*)NULL;
-
VuGen sets the contexts of the object to be created:
unsigned long dwClsContext = lrc_ulong("7");
-
VuGen sets a variable to hold the requested interface ID, which is IUnknown in this case:
GUID riid = IID_IUnknown;
-
After the input parameters are prepared, a call to lrc_CoCreateInstance creates an object using the parameters defined in the preceding statements. A pointer to the IUnknown interface is assigned to output parameter IUnknown_0. This pointer is needed for subsequent calls:
lrc_CoCreateInstance(=;pClsid, pUnkOuter, dwClsContext, =;riid, (void**)=;IUnknown_0, CHECK_HRES);
pClsid is the unique global CLSID of the object, which was converted from the student.student.1 ProgID.
dwClsContext contains the context of the object (in process, local, remote or combinations of these.)
riid contains the interface ID of the IUnknown interface.
The input parameters were prepared and explained above. Since the call succeeded, VuGen sets error checking on during the user simulation by inserting the CHECK_HRES value. The call returns a pointer to the IUnknown interface in IUnknown_0, that can be used in subsequent calls.
After creating an object, VuGen has access only to the IUnknown interface . VuGen uses the IUnknown interface for communicating with the object. This is done using the QueryInterface method of the IUnknown standard interface. The first parameter in a VuGen method call is the interface instance. In this case it is the IUnknown_0 pointer set previously by CoCreateInstance. The QueryInterface call requires as input the ID of the interface to be retrieved, and returns a pointer to the interface designated by that ID.
-
First, VuGen sets a parameter, riid, equal to the ID of the Istudent interface:
GUID riid = IID_Istudent;
-
A call to QueryInterface assigns a pointer to the Istudent interface to output parameter Istudent_0 if the Istudent object has such an interface:
lrc_IUnknown_QueryInterface(IUnknown_0, =;riid, (void**)=;Istudent_0, CHECK_HRES);
This example shows the how the interface was used to set data. Suppose that in the application, the user supports entering a name. This would activate a method for setting the name. VuGen recorded this in two statements: one statement was used for setting up the name string and the second one set the name property.
-
First, VuGen sets a variable (Prop Value) equal to the string. The parameter is of type BSTR, a string type used in COM files:
BSTR PropValue = lrc_BSTR("John Smith");
In subsequent stages, you will probably parameterize this call, replacing "John Smith" with a parameter, so that different names are used each time the Vuser script is run.
Next, VuGen calls the Put_Name method of the Istudent interface to enter the name:
lrc_Istudent_put_name(Istudent_0, PropValue, CHECK_HRES);
Returning data from an application is different than entering the data, because you might want to store these values and use them as inputs in subsequent calls for parameterization.
-
Create a variable of the appropriate type (in this case a BSTR) that contains the value of the property.
BSTR pVal;
Get the value of the property, in this case a name, into the pVal variable created above, using the get_name method of the Istudent interface in this example.
lrc_Istudent_get_name(Istudent_0, =;pVal, CHECK_HRES);
VuGen then generates a statement for saving the values.
//lrc_save_BSTR("param-name",pVal);
The statement is commented out. You can remove the comments and change <param-name> to a variable with a meaningful name to be used for storing this value. VuGen uses the variable to save the value of pVal returned by the previous call. You can then use the variable as a parameterized input in subsequent calls to other methods.
Most COM objects have specific interfaces. Many of them also implement a general-purpose interface called IDispatch, which VuGen translates in a special way. IDispatch is a "superinterface" that exposes all of the other interfaces and methods of a COM object. Calls to the IDispatch:Invoke method from VuGen scripts are implemented using lrc_Disp functions. These calls are constructed somewhat differently from calls to other interfaces.
The IDispatch interface Invoke method can execute a method, it can get a property value, or it can set a value or reference value for a property. In the standard IDispatch:Invoke method these different uses are signaled in a wflags parameter. In the VuGen implementation they are implemented in different procedure calls that invoke a method or put or get a property.
For example, a call to IDispatch to activate the GetAgentsArray method may look like this:
retValue = lrc_DispMethod1((IDispatch*)IDispatch_0, "GetAgentsArray", /*locale*/1033, LAST_ARG, CHECK_HRES);
The parameters in the above call are:
IDispatch_0
|
This is the pointer to the IDispatch interface returned by a previous call to the IUnknown:Queryinterface method.
|
GetAgentsArray
|
This is the name of the method to invoke. Behind the scenes, VuGen gets the ID of the method from the name.
|
1033
|
This is the language locale.
|
LAST_ARG
|
This is a flag to tell the IDispatch interface that there are no more arguments.
|
CHECK_HRES
|
This flag turns on checking of HRES, since the call succeeded when it was recorded.
|
In addition, there might be another parameter, OPTIONAL_ARGS. This signals that in addition to any standard parameters, VuGen is sending some optional arguments. Each optional argument consists of a pair giving the ID or name of the argument and its value. For example, the following call to lrc_DispMethod passes optional arguments "#3" and "var3":
{ GUID riid = IID_IDispatch; lrc_IOptional_QueryInterface(IOptional_0, =;riid, (void**)=;IOptional_0, CHECK_HRES); } { VARIANT P1 = lrc_variant_short("47"); VARIANT P2 = lrc_variant_short("37"); VARIANT P3 = lrc_variant_date("3/19/1901"); VARIANT var3 = lrc_variant_scode("4"); lrc_DispMethod((IDispatch*)IOptional_0, "in_out_optional_args", /*locale*/1024, =;P1, =;P2, OPTIONAL_ARGS, "#3", =;P3, "var3", =;var3, LAST_ARG, CHECK_HRES); }
The different lrc_Disp methods that use the IDispatch interface are detailed in the Function Reference (select the relevant version).
As shown in the above example, many COM parameters are defined as variants. To extract these values, VuGen uses a number of conversion functions, derived from the equivalent COM functions. The full list is given in the Function Reference (select the relevant version). Previously, it was shown how the lrc_DispMethod1 call was used to retrieve an array of name strings:
VARIANT retValue = lrc_variant_empty(); retValue = lrc_DispMethod1((IDispatch*)IDispatch_0, "GetAgentsArray", /*locale*/1033, LAST_ARG, CHECK_HRES);
The following example now shows how VuGen gets the strings out of retValue, which is a variant that is read as an array of strings.
First, VuGen extracts the BSTR array from the variant:
BstrArray array0 = 0; array0 = lrc_GetBstrArrayFromVariant(=;retValue);
With all the values in array0, VuGen provides you with code that you can use to extract the elements from the array for later use in parameterization, as in the example below:
//GetElementFrom1DBstrArray(array0, 0); // value: Alex //GetElementFrom1DBstrArray(array0, 1); // value: Amanda ....
VuGen has numerous type conversion functions and functions for extracting conventional types from variants. These are detailed in the Function Reference.