Featured

QTP 10 not Recognizing Oracle Forms Obje

Bidun Meduza shared on our Facebook page a problem and solution that I thought might be useful to you too. Problem He had a situation where QTP 10 was unable to recognize objects of Oracle Forms. Th

Read More
QTP 10 not Recognizing Oracle Forms Objects

New Navigation Menus

In order to ease orientation through our vast knowledge archive, we have added the following navigation menus: First Steps Scripting QTP VBScript Tutorial Knowledge Articles (by levels of expertise) B

Read More
New Navigation Menus

Permalinks

We’ve changed the permalinks format, so if you have been experiencing some trouble with finding materials with the old links, then remove the YYYY/MM/ from the URL and you’d be fine. In ca

Read More
Permalinks

Advanced QTP on Android

A first version of AdvancedQTP for Android can be found here. Now you can take this perfect companion with you to keep updated on what’s new in our site.

Read More
Advanced QTP on Android

New Advanced QTP Features: Layout and FB

As you have most surely noticed, we’ve recently changed the site’s theme in order to enhance the overall user experience. As from today, you can also register and login seamlessly with you

Read More
New Advanced QTP Features: Layout and FB Integration

Generate a GUID with COM

0
by on March 30, 2009 at 04:00

A QTip titled Generate GUID posted about a year ago by Dani Vainstein (2008) showed how to generate a GUID (Global Unique Identifer) by means of a implementing the algorithm with a function or by using uuidgen.exe (a Microsoft utility).

However, you can also use the good services of a COM object called Scriptlet.TypeLib to accomplish the same task. The snippet below shows how.

 

<span style="color: #0000ff;">Set</span> TypeLib = CreateObject(<span style="color: #006080;">"Scriptlet.TypeLib"</span>)

NewGUID = TypeLib.Guid

Msgbox NewGUID

, ,

Reserved Objects as an Env. Object Replacement

0
by on March 30, 2008 at 04:10

Today we’re gonna look at QTP’s internal mechanism for creating singleton COM objects, called Reserved Objects; And we’ll see how Reserved Objects can be used to improved and simplify our scripts.

Well, that was a heavy title… let’s see if we can break it down:
1. A COM object is any object you can create via CreateObject command (Scripting.Dictionary, Word.Application, etc.)
2. Singleton means that only a single instance of the reserved object can be created.
3. Internal mechanism means that if you’re gonna use it, it will include some registry tweaking.

Now that we’ve simplify things a bit, let’s move on.

QTP has a neat mechanism called Reserved Objects. Any COM object can be made into a Reserved Object, and will be accessible via QTP from there on.

So, why not create that object via CreateObject method, assign it to a variable, and just use it regularly? Reserved Objects have two major benefits:

1. They are created ONCE when a QTP script starts running, and are globally accessible. So they’re kinda like declaring a global variable, but in a much stronger, deeper sense. It can solve may of the pesky problems of unclosed system processes due to unclosed CreateObjects objects

2. Once an object is added to the reserved objects pool, it’s accessible via QTP’s auto-complete. This means that both the object’s name, and internal methods & properties will be auto-completed. Which is kinda cool.


Reserved Object can be used to simplify and organize many tasks: file IO, log writing, using excel / word / outlook etc. I specifically love using Reserved Objects to replace the Environment object.

The environment object is supposed to give you a global data storage, but I just find it too restrictive. It can only house simple variable types, which means you can forget about passing objects globally; There is no simple way for looping through all the values; And many more annoying “features”.

So, instead of using the Environment object, I create my own Scripting.Dictionary reserved object (as seen in the screen captures), which allows me to host any number of sub-values, ranging from a string, a QTP object, a nested dictionary, to just about anything. I can then loop through the values by numbers, keys, or items, and have complete freedom in my code. I know it’s kinda hard to notice, but I REALLY love the dictionary object…


So, how do we actually create reserved object?

This part is all about editing the registry. AdvancedQTP takes no direct or indirect responsibility registry tweaking. Do this at your own risk, and you better know what you’re doing…

But ’nuff chit-chat.

Here’s the thing: Open your registry and go to :
HKEY_CURRENT_USER\Software\Mercury Interactive\QuickTest Professional\MicTest\ReservedObjects\

There you’ll see many of QTP’s internal object. DO NOT MESS WITH THEM.
Next, create a new key, with the name of the reserved object (e.g. Advanced QTP)

Enter the key “folder”, and create these values :
ProgID (string) – Holds the COM program ID we want to create (e.g. Scripting.Dictionary)
VisibleMode (dWord) – Holds the value 2. This controls the auto-complete and intellisense appearance.
UIName (string) – The name that will refer to the reserved object. Make sure this is the same as the key name.

There are more properties, which control the icon of the object, and other options. Sadly, I while trying to figure them out, I’ve messed my QTP a bit, so I’ve stopped experimenting. If you know of more properties, please let me know.

And that’s it. The next time you’ll open QTP, the reserved object will be accessible through the auto-complete from all the scripts and functions.

Have fun :)

in Articles, Yaron Assa

, , , ,

Intellisense and COM

0
by on March 30, 2008 at 03:59

In a previous article, I’ve discussed (among other things) the possibility of adding COM objects to the QTP reserved objects pool, thereby enabling some limited sort of intellisense for them (i.e. Syntax auto-complete).

This is all very nice, but what happens when we want to do something similar with our custom classes and objects? It seems that since the process involves specifying the object’s COM ProgID, we can only add “proper” objects to the QTP reserved objects pool (e.g. Excel.Application or Scripting.Dictionary objects). For those of us who use custom classes and object on an everyday basis, this becomes a huge limitation on the method.

Well, have no fear, a solution is here. MilindCD from SQAForums has published a solutionwhich allows us to write our own classes, create a COM wrapper around them, and then add them to the QTP reserved objects pool. It can be quite cool as it allows us to create custom extensions of VBScript’s “regular” objects, and use them with a kind of limited intellisense.

Let’s go through the solution and see how it’s done.

The Specifics

First of all, a little disclaimer, this will only give you VERY limited intellisense. If you want true intellisense in QTP you’ll either have to either bang your had against the wall in frustration, or install Test Design Studio, which extends QTP, and enables intellisense similar to that in Visual Studio.

Now we can move on to the specifics. First of all we need to introduce a new type of file: Windows Script Component. For our purpose, a windows script component (WSC) is just an XML file with a VBScript class contents and some Meta-data which describes the code. So it’s the plain old VBScript code you’ve known and loved, with some lines that talk about the code and allows windows to better understand it.

What we’re going to do is to use the Meta-data to register our custom class to COM. Once we’ve done that, we can easily add the new COM object to QTP’s reserved objects pool (in this point, our custom COM object has the same status as a Scripting.Dictionary or Excel.Application “Proper” object), and get instant intellisense for it.

The structure of WSC

We won’t get into ALL the possibilities available in writing WSC files, just the basics needed to register our VBScript class to COM. You can explore the rest on your own in either the MSDN documentation on the matter, or just Google it.

First, it’s an XML file, so the basic skeleton is your run of the mill open-close tag wrapper, with “component” as the central tag (there is a possibility to wrap several components in a single package tag, but we won’t get into that):

<span style="color: #0000ff;"><?</span><span style="color: #800000;">xml</span> <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1.0"</span>?<span style="color: #0000ff;">></span>
<span style="color: #0000ff;"><</span><span style="color: #800000;">component</span> <span style="color: #ff0000;">id</span><span style="color: #0000ff;">="MyQTPClass"</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">component</span><span style="color: #0000ff;">></span>

The id part is optional (if you only have one component in the file), so we could have just written <component>. I think it’s better to organize our code with identifiers even when it’s not necessary.

Within the component we can add a special instruction which will validate our XML structure before registering the component to COM. This is a very important option to include:

<span style="color: #0000ff;"><?</span><span style="color: #800000;">component</span> <span style="color: #ff0000;">error</span><span style="color: #0000ff;">="true"</span> <span style="color: #ff0000;">debug</span><span style="color: #0000ff;">="true"</span>?<span style="color: #0000ff;">></span>

Next comes the part which specifies the COM registration data:

<span style="color: #0000ff;"><</span><span style="color: #800000;">registration</span>
    <span style="color: #ff0000;">description</span><span style="color: #0000ff;">="AdvancedQTP Custom Class Example"</span>
    <span style="color: #ff0000;">progid</span><span style="color: #0000ff;">="AdvancedQTP.CustomClass"</span>
    <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1"</span>
    <span style="color: #ff0000;">classid</span><span style="color: #0000ff;">="{7cf11854-dcf4-40cc-9a11-b365f0a734ef}"</span>
<span style="color: #0000ff;">/></span>

Well, let’s see what we got here. The registration tag is composed of several attributes. Description and Version are optional attributes meant for documentation purposes only. ProgID will be the unique COM name by which our custom control will be identified (i.e., it’s the string you send to the CreateObject method to create your class instance). Classid is a GUID unique identifier which identifies our class in the registry (you can find random GUID generators that will give you a GUID to put in the part – just search GUID generator in Google).

This pretty much gives windows everything it needs in order to register our class to COM. Well, except the actual class code, and how it can be used. Let’s begin with how it can be used. We need to tell COM what are the public properties and methods available in our class:

<span style="color: #0000ff;"><</span><span style="color: #800000;">public</span><span style="color: #0000ff;">></span>
   <span style="color: #0000ff;"><</span><span style="color: #800000;">property</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ID"</span> <span style="color: #ff0000;">get</span><span style="color: #0000ff;">="ReturnID"</span> <span style="color: #ff0000;">put</span><span style="color: #0000ff;">="SetID"</span><span style="color: #0000ff;">/></span>
   <span style="color: #0000ff;"><</span><span style="color: #800000;">method</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="PrintMessage"</span><span style="color: #0000ff;">></span>
               <span style="color: #0000ff;"><</span><span style="color: #800000;">parameter</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="Message"</span><span style="color: #0000ff;">/></span>
   <span style="color: #0000ff;"></</span><span style="color: #800000;">method</span><span style="color: #0000ff;">></span>
<span style="color: #0000ff;"></</span><span style="color: #800000;">public</span><span style="color: #0000ff;">></span>

As you can see, we can describe both the name of the functions and properties, and the parameters they take. By defining both Get and Put elements for the ID property we set it as read/write, but we could’ve only used the read part, or map the property directly to an inner variable. There are many other options available to you through the MSDN documentation.

And now, last but not least, the actual code of our class (ignore the inner line numbers, there’re not part of the code):

<span style="color: #0000ff;"><</span><span style="color: #800000;">script</span> <span style="color: #ff0000;">language</span><span style="color: #0000ff;">="VBScript"</span><span style="color: #0000ff;">></span>
<span style="color: #606060;"> 1:</span>
<span style="color: #606060;"> 2:</span> <![CDATA[
<span style="color: #606060;"> 3:</span>             Dim pID
<span style="color: #606060;"> 4:</span>             Function ReturnID()
<span style="color: #606060;"> 5:</span>                         ReturnID = pID
<span style="color: #606060;"> 6:</span>             End Function
<span style="color: #606060;"> 7:</span>             Function SetID (sValue)
<span style="color: #606060;"> 8:</span>                         pID = sValue
<span style="color: #606060;"> 9:</span>             End Function
<span style="color: #606060;"> 10:</span>             Function PrintMessage(Message)
<span style="color: #606060;"> 11:</span>                         Msgbox Message
<span style="color: #606060;"> 12:</span>             End Function
<span style="color: #606060;"> 13:</span>       ]]>

</script>

Well, it’s pretty much a cut-and-paste version of the script, wrapped in an XML <script> tag and a CDATA section. The only noticeable change is that our property is implemented through functions.

Wrapping it all together

So, to summarize, our complete WSC file should look something like this (ignore the inner line numbers, there’re not part of the code):

<span style="color: #0000ff;"><?</span><span style="color: #800000;">xml</span> <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1.0"</span>?<span style="color: #0000ff;">></span>
    <span style="color: #0000ff;"><</span><span style="color: #800000;">component</span> <span style="color: #ff0000;">id</span><span style="color: #0000ff;">="MyQTPClass"</span><span style="color: #0000ff;">></span>
    <span style="color: #0000ff;"><?</span><span style="color: #800000;">component</span> <span style="color: #ff0000;">error</span><span style="color: #0000ff;">="true"</span> <span style="color: #ff0000;">debug</span><span style="color: #0000ff;">="true"</span>?<span style="color: #0000ff;">></span>
    <span style="color: #0000ff;"><</span><span style="color: #800000;">registration</span> <span style="color: #ff0000;">description</span><span style="color: #0000ff;">="AdvancedQTP Custom Class Example"</span> <span style="color: #ff0000;">progid</span><span style="color: #0000ff;">="AdvancedQTP.CustomClass"</span> <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1"</span> <span style="color: #ff0000;">classid</span><span style="color: #0000ff;">="{7cf11854-dcf4-40cc-9a11-b365f0a734ef}"</span><span style="color: #0000ff;">/></span>
    <span style="color: #0000ff;"><</span><span style="color: #800000;">public</span><span style="color: #0000ff;">></span>
        <span style="color: #0000ff;"><</span><span style="color: #800000;">property</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="ID"</span> <span style="color: #ff0000;">get</span><span style="color: #0000ff;">="ReturnID"</span> <span style="color: #ff0000;">put</span><span style="color: #0000ff;">="SetID"</span><span style="color: #0000ff;">/></span>
            <span style="color: #0000ff;"><</span><span style="color: #800000;">method</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="PrintMessage"</span><span style="color: #0000ff;">></span>
                <span style="color: #0000ff;"><</span><span style="color: #800000;">parameter</span> <span style="color: #ff0000;">name</span><span style="color: #0000ff;">="Message"</span><span style="color: #0000ff;">/></span>
            <span style="color: #0000ff;"></</span><span style="color: #800000;">method</span><span style="color: #0000ff;">></span>
    <span style="color: #0000ff;"></</span><span style="color: #800000;">public</span><span style="color: #0000ff;">></span>
    <span style="color: #0000ff;"><</span><span style="color: #800000;">script</span> <span style="color: #ff0000;">language</span><span style="color: #0000ff;">="VBScript"</span><span style="color: #0000ff;">></span>
<span style="color: #606060;"> 1:</span>
<span style="color: #606060;"> 2:</span>         <![CDATA[
<span style="color: #606060;"> 3:</span>             Dim pID
<span style="color: #606060;"> 4:</span>             Function ReturnID()
<span style="color: #606060;"> 5:</span>                         ReturnID = pID
<span style="color: #606060;"> 6:</span>             End Function
<span style="color: #606060;"> 7:</span>             Function SetID (sValue)
<span style="color: #606060;"> 8:</span>                         pID = sValue
<span style="color: #606060;"> 9:</span>             End Function
<span style="color: #606060;"> 10:</span>             Function PrintMessage(Message)
<span style="color: #606060;"> 11:</span>                         Msgbox Message
<span style="color: #606060;"> 12:</span>             End Function
<span style="color: #606060;"> 13:</span>           ]]>
<span style="color: #606060;"> 14:</span>

</script>

<span style="color: #0000ff;"></</span><span style="color: #800000;">component</span><span style="color: #0000ff;">></span>

Now we can save the file, right-click it from windows, and we’ll have the option to register it to COM. Once our class is indeed registered to COM, we can create it in our script via the CreateObject(“Advancedqtp.CustomClass”) command, or add it to the reserved objects pool as previously described.

WSC has many more tricks and hacks in it, and you can find them by sieving through the extensive Microsoft documentation and general articles available on the net. I hope that this article will provide you with the starting point you need in order to do so.

in Articles, Yaron Assa

, , ,