Background
Today we’re going to deal with an often overlooked feature of QTP – RegisterUserFunc. Though RegisterUserFunc can offer some real-world benefits, newcomers to the QTP world are unfamiliar with it, and QTP experts look down on it (when comparing it to their custom frameworks). I intend to shed some new light on this feature and its inherent possibilities, and make it more accessible to and appealing to newcomers and experts alike.
RegisterUserFunc allows you to add a new method or override an existing method for a certain QTP class. For example, you can add a new method called "Move20″ to all VBWindows in your scripts, which will move them 20 pixels to the right; or override the VBWindow "Close" method by adding your own code for dealing with "save changes" pop-ups that may appear when you try to close them.
Either way, RegisterUserFunc shifts the way of extending your scripts power and functionality from writing functions which receive objects and operate on them, to adding methods to the relevant objects themselves.
Syntax
Using RegisterUserFunc is rather simple, and is comprised to two phases.
First, we write the code for the new method as a function, which receives at least one parameter. We can functions methods that receive more than one parameter, thus making it possible to override methods such as Set or Select (which require sending the desired new value as a parameter by itself). The first parameter the function receives is always the object that initiated the method. So if we take the previous example, our function will look like this:
Function MyClose(oWindow)
Dim iTimer 'Will help us count time
iTimer = Timer
oWindow.Close 'Initiate the VBWindow original close command
Do
If Dialog("micclass:=Dialog").Exist(0) Then _
Dialog("micclass:=Dialog").Type MicEsc
'Deal with any pop-ups
Loop Until (Not oWindow.Exist) Or (Timer-iTimer>15)
'Wait for the window to close or the command to time out
If oWindow.Exist Then
MyClose = False
Else
MyClose = True
End If
End Function
After that, we need to actually register our new method to the VBWindow QTP class. This is done with the RegisterUserFunc command (for the complete command syntax, see QTP help):
RegisterUserFunc "VBWindow", "Close", "MyClose"
This will register the function MyClose, as a VBWindow’s class method named "Closed". Since this QTP class already has a method called Closed, our new method will override it for this run-session.
Scope and deregistration
It’s important to note that the scope of RegisterUserFunc is determined by the scope of the code it was called from. So for example, if we call RegisterUserFunc from within an action, it will not affect the objects in other actions (though they may be used in the same run-session). To achieve a more global effect, you should place both the function code and the RegisterUserFunc command in an external vbs, and link it to your tests.
Moreover, if at some point DURING the run-session you’d like to remove your method from the QTPClass, you can use UnRegisterUserFunc to do so. QTP help advises you to UnRegisterUserFunc any method that was registered within the scope of the current action, though I don’t really understand why.
Maintenance and RegisterUserFunc
While the common opinion among QTP experts is that RegisterUserFunc is no match for a well-built custom framework, it still has its benefits and merits - The central one being the ability to apply script-wide code-fixes without changing a single line of existing code.
Imaging the following situation – you have a wide system of scripts automating an AUT which contains comboboxes. After a while, the client comes with a new requirement - select an unknown random value in the comboboxes.
Now, in the preferable situation, you have a custom framework wrapping the input command for the AUT’s controls, and you can easily introduce the needed code in one central place, and get done with it (for example, this is the case with FrameworkManager). However, if you don’t have such a framework, adding the new code becomes a hellish run of all the tests and scripts, fixing every code-line that deals with inputting comboboxes.
RegisterUserFunc can save you all those nitpicking micro code-fixes. You can write an extended function that will manage the random value selection, and override the combobox default .Select method with it. This way, you can implement the new behavior throughout all your tests and scripting with a single command. Here’s a possible implementation for the function:
Function ComboSelectWithRandom(oCombo, sNewValue)
Dim iRndValue
Dim arrAllValues
If uCase(sNewValue) = "RANDOM" Then
'Transform the comboboxes "all values" property into an array
arrAllValues = Split(oCombo.GetROProperty("all items"), chr(10))
'Randomly select a new value
iRndValue=RandomNumber.Value(0, uBound(arrAllValues))
sNewValue = arrAllValues(iRndValue)
End If
'Try actual value selection
On Error Resume Next
oCombo.Select sNewValue
If Err.Number <> 0 Then
ComboSelectWithRandom = False
Else
ComboSelectWithRandom = True
End If
On Error Goto 0
End Function
And now we only need to override the default .Select command:
RegisterUserFunc "VbComboBox", "Select", " ComboSelectWithRandom"
And we can immediately start selecting "Random" in all our scripts and tests. So while it’s better to have a robust framework that will save you these emergencies, if you’re already knee-deep in a crises, RegisterUserFunc can help you get out of it in a fast and easy manner.
Posted in QTP Techniques

Yaron Assa




May 18th, 2008 at 10:08 pm
[…] topic has already been addressed by Yaron Assa in “A Fresh Look on RegisterUserFunc” (2008). In this brief article we will see that it is also technically possible to override object […]
May 26th, 2008 at 10:25 am
Pretty useful for override existing user-defined or system-defined function without affecting the original framework or function.
May 30th, 2008 at 11:16 pm
[…] method for implementing such an extensibility follows the same lines outlined in Yaron Assa’s “A Fresh Look on RegisterUserFunc” (2008) and my own previous article (Bar-Tal, 2008b) in which I explained the motivation to override […]
July 4th, 2008 at 7:29 pm
very good
October 16th, 2008 at 2:21 pm
Nice article. I would be inerested to know that how we can use the above method instead of Recovery Scenario in QTP. Agreed that the Recovery Scenario is not 100% reliable and makes the execution very slow. However, one benefit of it is that it can handle the popup or errors at any point in the application.
With above method we should know that exactly at which step in the application we will get the VBWindow popup and have to perform the close operation to call the RegisteredUserFunction.
It can not handle unexpected popups. Please correct me if I am wrong.
Thanks,
Kapil.