Relevant Codes

A Test Development Resource for HP QuickTest Professional.

QTP: Working With Multiple Windows Applications

November 26, 2009 · 6 comments

After writing the article Working with Multiple Browser Applications with QTP, I thought, there are several instances where automation developers have to work with applications containing multiple windows, in a Standard Windows Environment. This technique uses a similar methodology as demonstrated in the article for Web-based apps, but the crux of this technique differs. It can be used by automation developers testing most types of windows applications, and it contains concepts that are showcased in my generic automation framework RelevantCodes[1]One, which will be released in the coming few weeks.

With the help of this technique, regardless of how many windows applications are opened through QTP, we would never have to keep track of the Window’s title or any of its recognition properties (unless we want to). In other words, regardless of a window’s dynamic nature, this concept will enable you to give the window a name of your choice, and use that name to identify the window, instead of keeping track of changes in its properties.

What this concept contains:

  • LaunchAdd: Launch a new window and retain its reference throughout the test cycle
  • AddNew: Automatically add a new open window to the collection without you having to specify its properties (see list of dependencies)
  • AddCustom: Adds a custom window by specifying its properties as an array
  • All identifiers stay intact until the test finishes.

View clsWindow.txt | Download clsWindow.zip | Download Demo v9.2 | Download Demo v9.5

This concept contains 3 main methods, as described above. You can download the Class clsWindow for complete documentation, but for a quick overview, please continue reading.

First, and the one that may be used the most often is a method called AddCustom. It enables users to add a window of their choice to the collection, with the name they want to specify. From that point onwards, regardless of the number of changes that particular window goes through, it will not be required to update its properties. The name you give the window can be used throughout the test cycle. Below is the code snippet for AddCustom:

Public Sub AddCustom(arrPropertyValue, sName)
    Dim lngHwnd
 
    Me.sName = sName
    Me.arrPropertyValue = arrPropertyValue
 
    'Retrieve the handle of the specified window
    lngHwnd = GetCustomWindowHwnd()
 
    'If the handle is valid, then add it to the global collection
    If lngHwnd <> -1 Then
        colObject.Add sName, Window("hwnd:=" & lngHwnd)
        If Not oDict.Exists(lngHwnd) Then
            oDict.Add lngHwnd, lngHwnd
        End If
    End If
End Sub

Next is a method called LaunchAdd, which is dependent upon GetRecentlyOpenWindowHwnd. This will enable you to automatically add a newly launched window to the collection, with the name you specify:

Public Sub LaunchAdd(sFilePath, sName)
    Dim lngHwnd
 
    Me.sFilePath = sFilePath
    Me.sName = sName
 
    'Retrieve the window handle of the recently launched window
    lngHwnd = GetRecentlyOpenWindowHwnd()
 
    'If the handle is valid, then add it to the global collection object
    If lngHwnd <> -1 Then
        colObject.Add sName, Window("hwnd:=" & lngHwnd)
        If Not oDict.Exists(lngHwnd) Then
            oDict.Add lngHwnd, lngHwnd
        End If
    End If
End Sub
 
Private Function GetRecentlyOpenWindowHwnd() 'As Integer
    Dim sFilePath, sName, oDesc, oParent, mHwndDict, x, iTimeElapsed
 
    sFilePath = Me.sFilePath
    sName = Me.sName
 
    GetRecentlyOpenWindowHwnd = -1
 
    On Error Resume Next
 
        'Create a description object
        Set oDesc = Description.Create
 
        'oParent holds references to all the open windows
        Set oParent = Desktop.ChildObjects(oDesc)
 
        'Scripting.Dictionary: holds all open windows' handles
        Set mHwndDict = CreateObject("Scripting.Dictionary")
 
        'Loop until all the handles are successfully added to the collection
        For x = 0 to oParent.Count - 1
            mHwndDict.Add oParent(x).GetROProperty("hwnd"), x
            If Not oDict.Exists(oParent(x).GetROProperty("hwnd")) Then
                oDict.Add oParent(x).GetROProperty("hwnd"), oParent(x).GetROProperty("hwnd")
            End If
        Next
 
        'Launch the target application
        SystemUtil.Run sFilePath
 
        'Loop max 10 seconds for the window to open
        Do
            Set oParent = Desktop.ChildObjects(oDesc)
            For x = 0 to oParent.Count - 1
                Select Case oParent(x).GetTOProperty("micclass")
	       Case "Window", "Dialog"
                        If Not mHwndDict.Exists(oParent(x).GetROProperty("hwnd")) Then
                            GetRecentlyOpenWindowHwnd = oParent(x).GetROProperty("hwnd")
                            Exit Do
                        End If
                End Select
            Next
            Wait(1)
            iTimeElapsed = iTimeElapsed + 1
        Loop Until iTimeElapsed = 10 
 
        Set oDesc = Nothing
        Set oParent = Nothing
        Set mHwndDict = Nothing
 
    On Error Goto 0
End Function

Lastly, and a tricky one is AddNew. This will automatically add any new open window after LaunchAdd has been executed. Like the other 2 methods, this method will also enable preservation of a window’s property until the end of the test.

Public Sub AddNew(sName, iTimeOutBeforeWindowOpens)
    Dim oDesc, oParent, x, iTimeElapsed, lngHwnd
 
    'Set default application timeout
    If iTimeOutBeforeWindowOpens = "" Then
        iTimeOutBeforeWindowOpens = 1
    End If
 
    'Create a Description Object
    Set oDesc = Description.Create
 
    'oParent holds all open windows
    Set oParent = Desktop.ChildObjects(oDesc)
 
    'Wait iTimeOutBeforeWindowOpens number of seconds
    'Default iTimeOutBeforeWindow Opens = 1
    Wait(iTimeOutBeforeWindowOpens)
 
    'Loop for 5 seconds
    'If within 5 seconds, a new unadded window is found, the window will
    ' be added to the collection and this procedure will end.
    Do 
        'Create a new collection
        Set oParent = Desktop.ChildObjects(oDesc)
 
        'Loop for all objects in the collection and find a one that does
        'not exist in the global dictionary: colWindows
        For x = 0 to oParent.Count - 1
            If Not oDict.Exists(oParent(x).GetROProperty("hwnd")) Then
                lngHwnd = oParent(x).GetROProperty("hwnd")
                oDict.Add lngHwnd, lngHwnd
                colObject.Add sName, Window("hwnd:=" & lngHwnd)
                Exit Do
            End If
        Next
        Wait(1)
        iTimeElapsed = iTimeElapsed + 1
    Loop Until iTimeElapsed = 5 'This timeout can be minized to 1, if desired
End Sub

View clsWindow.txt | Download clsWindow.zip | Download Demo v9.2 | Download Demo v9.5

Technically, the concepts in this article can be easily transferred to any technology, just like the concepts were transferred from Web to Windows, which is quite a huge transition. Once this concept is implemented properly, it should help eliminate the need to constantly identify the windows we need to work with.

I hope you find this helpful :)

If you have any questions, please ask them in the comments section. If your query is confidential, please use the Contact Form to send me an e-mail instead.

{ 6 comments… read them below or add one }

1 Puneet Varma February 4, 2010 at 1:51 pm

Hi Anshoo,

If you can help me with this problem, how i can get the wildcard on the window name below or the object repository.

SwfWindow(“HA – [Server IP]“).SwfEdit(“txtServerIp”).Set IP
SwfWindow(“HA – [Login Mode]“).Activate
SwfWindow(“HA – [Login Mode]_2″).Activate

Reply

2 Anshoo Arora February 4, 2010 at 1:55 pm

Hi Puneet,

Do you intend to insert the wildcard through DP or OR?

Reply

3 Puneet February 4, 2010 at 1:57 pm

Which ever is easier.

Reply

4 Anshoo Arora February 4, 2010 at 2:01 pm

Try this:

SwfWindow(“swfname:=.*Server.*]“).SwfEdit(“swfname:=txtServerIp”).Set IP
SwfWindow("swfname:=.*Login Mode.*")Activate

If its not the swfname property in the object spy for these object, please change it to the correct property. But, the wilcard rule is quite simple here. .* matches any character 0 or more number of times.

Reply

5 Puneet February 4, 2010 at 2:01 pm

OR would be easier b/c then you don’t have to see a big mess of OR and easy to maintain.

Reply

6 Anshoo Arora February 4, 2010 at 2:15 pm

Puneet,

In the object’s properties window, you can check the box “regular expression” and add the correct regular expression there (see the post above).

Reply

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Previous post:

Next post: