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.
{ 8 comments… read them below or add one }
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
Hi Puneet,
Do you intend to insert the wildcard through DP or OR?
Which ever is easier.
Try this:
SwfWindow(“swfname:=.*Server.*]“).SwfEdit(“swfname:=txtServerIp”).Set IP SwfWindow("swfname:=.*Login Mode.*")ActivateIf its not the
swfnameproperty 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.OR would be easier b/c then you don’t have to see a big mess of OR and easy to maintain.
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).
I use low-level recording for IE to record flash element.
I use something like this:
WindowObject.LaunchAdd “iexplore.exe”, “Windows Internet Explorer”
and instead of
Window(“Windows Internet Explorer”).WinObject(“MacromediaFlashPlayerActiveX”)
in my code I write
WindowObject.Name(“Windows Internet Explorer”).WinObject(“Name:=MacromediaFlashPlayerActiveX”)
but WinObject is not recognized.
What am I doing wrong?
Danijela,
Does the WinObject have a name property that equals to MacromediaFlashPlayerActiveX? Any example that I can use to test this?