Avoid Pure Virtual Function Call Error with Mercury.ObjectRepositoryUtil !!


We shall look into the ObjectRepositoryUtil object and an issue we will face if we do not properly release the object before exiting the program. An important note here is that we do not need to open QTP while developing code using the automation object model. We just need a .vbs (VB script) file to work with QTP's automation object model. I will not go into details of this but rather focus on the topic we are going to discuss.


When creating an object using Mercury.ObjectRepositoryUtil we must ensure that the objects are released after its use. Else we will get thrown with an exception, the "dreaded" R6025 - pure virtual function call error. This exception causes QTP to crash !!!



The exception would be thrown if you are not properly "releasing" the memory. Releasing memory attached to an object is achieved by "Set"ting your object to "Nothing".

For testing this lets first get prepared...
We first need a shared repository. For that, open a script you already have and go to Resources->Object Repository and then File -> Export Local Objects. Save your file as "C:\shared.tsr"
Now..lets open a new test and enter the following code

Set RepositoryFrom = CreateObject("Mercury.ObjectRepositoryUtil")
RepositoryFrom.Load "C:\shared.tsr"
Set FromCollection = RepositoryFrom.GetChildren("Test Objects")
For itemno = 0 To FromCollection.Count - 1
Set TestObject = FromCollection.Item(itemno)
Msg = RepositoryFrom.GetLogicalName(TestObject)
MsgBox Msg
Set TestObject = Nothing 'Important to release memory <== Try commenting this line to see the error ;)
Next
Set FromCollection = Nothing 'Important to release memory
Set RepositoryFrom = Nothing 'Important to release memory


This is how your program should be. Always remember to release objects while playing with shared repositories to avoid getting the virtual function call error causing QTP to crash.
I dont want to have any sort of copyright or copyleft in this site but if you are reusing this code in any other site, I would appreciate you to provide this page as a link so that others get a more descriptive explanation of this concept. Your suggestion and comments are always welcome. Cheers !!!
As always,
Your friend in need,

George, Reju

Read Users' Comments (9)

9 Response to "Avoid Pure Virtual Function Call Error with Mercury.ObjectRepositoryUtil !!"

  1. Unknown says:
    November 11, 2009 at 2:15 PM

    I just installed QTP 10 on a vm image and although the installation is successful QTP will not run without throwing this error. Trying to run the program brings up zero dialogs, it thinks for about 5 seconds then brings up the warning message shown above. Do you know any reason that QTP would be failing like this?
    (running on a WinXP 32bit vmware image)

  2. REJU GEORGE says:
    November 11, 2009 at 2:26 PM

    1. Did you install QTP as administrator on the VM image ?
    2. By trying to run the program, do you mean trying to open QTP or a test ?

    - Reju -

  3. Unknown says:
    November 12, 2009 at 3:26 AM

    Hi Reju,

    I exactly got what i was looking for.
    I want a little more than this. I need your help.

    In the same code I want FromCollection to be declared as public so that when I call this function again i want to use this same instead of getting the FormCollection again and again.

    Or Another option could be is there a way that I can copy this FormCollection to another Object and declare it public.

    Please let me know. I need this asap.

    It would be of a great help.

    Thanks in advance,
    Ramadas Kaipa

  4. REJU GEORGE says:
    November 12, 2009 at 5:59 AM

    Hi Ramadas,
    From what you mentioned it looks like you put this code in a function. Is that right ? Is the function in your action itself or have you put it in a function library ? Just declare the variable FromCollection outside the scope of the function ...

    Dim FromCollection
    Function ObjRepLogicalNameGet ()

    '==============
    ' Function code
    ' =============
    End Function

    - Reju -

  5. Unknown says:
    November 12, 2009 at 9:06 AM

    Hi Reju,

    Thanks for response. You are right. I tried keeping the Object declaration outside. still i get this.

    But I want this declaration as public as this Function will be called many times and I want to keep this Object(FromCollection = OBJ_TOCollection ) value remembered when this function called next time.

    Here is my original code. Please let me know if this is possible.

    Dim OBJ_TOCollection
    'Public OBJ_TOCollection

    Function getClass(parent, element)
    'Author: psreekan
    'Date Created: 09/15/2008
    'Last Modified: 09/30/2008
    'Synopsys
    'Get the class for the element /parent combo

    Dim bFound
    getClass = Null
    bFound = False
    'Ramadas Kaipa added to reduce the time for fetching the TOCollection everytime
    If (StrComp(STR_PARENT,parent) = 0) And (StrComp(STR_ELEMENT,element) = 0) Then
    getClass = STR_CLASS
    Set TOCollection = OBJ_TOCollection
    ElseIf (StrComp(STR_PARENT,parent) = 0) And (StrComp(STR_ELEMENT,element) <> 0) Then
    Set TOCollection = OBJ_TOCollection
    STR_ELEMENT = element
    intCount = TOCollection.Count
    If (StrComp(element,"srcList") = 0) Or (StrComp(element,"destList") = 0) Then
    getClass = "FlexList"
    ElseIf (StrComp(element,"addToDestButton") = 0) Or (StrComp(element,"addAllToDestButton") = 0) Or (StrComp(element,"removeFromDestButton") = 0) Or (StrComp(element,"removeAllFromDestButton") = 0) Then
    getClass = "FlexImage"
    Else
    For i = 0 To TOCollection.Count - 1
    Set TestObject = TOCollection.Item(i)
    Msg = myRep.GetLogicalName(TestObject)
    If (StrComp(Msg,element) = 0)Then
    bFound = True
    getClass = TestObject.GetTOProperty("Class Name")
    STR_CLASS = getClass
    Exit For
    End If
    Next
    End If
    Else
    Set TOCollection = myRep.GetChildren(getObj(parent))
    STR_PARENT = parent
    STR_ELEMENT = element
    OBJ_TOCollection = TOCollection.CopyObject(Object)
    intCount = TOCollection.Count
    For i = 0 To TOCollection.Count - 1
    Set TestObject = TOCollection.Item(i)
    Msg = myRep.GetLogicalName(TestObject)
    If (StrComp(Msg,element) = 0)Then
    bFound = True
    getClass = TestObject.GetTOProperty("Class Name")
    STR_CLASS = getClass
    Exit For
    End If
    Next
    End If

    'Ramadas Kaipa commenting the Code by Sreekanta earlier
    ' Set TOCollection = myRep.GetChildren(getObj(parent))
    If Not bFound Then
    logger "error", "Object " & parent & " - " & element & "not found in the repository"
    Reporter.ReportEvent micFail, "GUI Object", "Object " & parent & " - " & element & " not found in the repository"
    End If
    Set TOCollection = Nothing
    End Function

  6. REJU GEORGE says:
    November 12, 2009 at 6:46 PM

    I dont see a reason why the value should not be saved. Probably you would need to confirm that the statement OBJ_TOCollection = TOCollection.CopyObject(Object) is indeed being executed. Let me give you an example to show how the scope works...

    Dim blnCheck
    blnCheck = False

    Function checkScope ()
    Dim intX

    intX = 3
    If blnCheck Then
    msgbox intX
    End If
    blnCheck = True
    End Function

    checkScope
    checkScope

    If you try commenting one of the function call to checkScope you will see that the msgBox would not appear. But if you call the function twice the msgbox would be shown and thats because the value blnCheck is remembered. So the only thing I suspect is that the statementI mentioned above is not being executed.

    - Reju -

  7. ttguy says:
    May 13, 2010 at 6:40 PM

    I have been doing stuff very similar to what I think RAMADAS is trying to do and I also had a hell of a time with the "R6025 - pure virtual function call error". And I can confirm that it is due to not releasing the objects.
    What you need to do is declare a global variable (with a dim statement) for your ObjectRepositoryUtil at the start of an attatched function library. I call mine gblObjectRepositoryUtil.
    Then in an action that only executes one time you populate the gblObjectRepositoryUtil with a .Load call.

    Then in the rest of the script you can repeatedly refer to gblObjectRepositoryUtil.

    But the important thing is that as the last step in your test - and in a step that only executes once do a set gblObjectRepositoryUtil = nothing.

    I note that RAMADAS wants to have a global OBJ_TOCollection. This should work OK to. But I have also noticed that you run into trouble if you do not release the TOCollection collection that you retrieve from the ObjectRepositoryUtil. And I have found that you need to release any test objects that you get from your TOCollection too.
    So you should do a set OBJ_TOCollection = nothing at the end of your script too if you have a OBJ_TOCollection declared globally.

    And one final gotcha I found with all this - I solved some intermitant errors by having my test make a local copy of the .tsr file holding my object repository and then have the .Load method of the ObjectRepositoryUtil object load that version up into memory - rather than have my test and the ObjectRepositoryUtil object share the same instance of the object repository.

    ttguy

  8. Anonymous Says:
    February 8, 2013 at 2:36 AM

    Thanks, there's a good reference on pure virtual functions here as well:

    pure virtual function call

  9. Anonymous Says:
    March 30, 2013 at 8:13 AM

    Hi Regu,
    When I try to click Open button, I get actactly the same above error and my QTP closes. I have only one script called "Gamil_para.tsr" under "C:\Program Files\HP\QuickTest Professional\Tests" folder. So, I copied "Gamil_para.tsr" from Tests folder to "C:\Program Files\HP\QuickTest Professional" and renamed to "shared.tsr". Then, I open a new script and copied the above code (as you suggested and changed the for shared.tsr). When I try to save the script, I am getting an error and QTP closes.
    Could you please tell me, what should I do in avoid the error.

    Thanks
    Shobha

Post a Comment

Visitors

Website Counter