Click to See Complete Forum and Search --> : How to get handles to dialogs and close them using the same


MadhavitRao
December 21st, 2004, 08:26 AM
Hi,

We are writting an application to automate the process of 'User Interface' testing.

During this process, some unwanted and erroneous dialogs of the tested application will remain open. (we will not have any information on these dialogs.)

We will have to close these dialogs as and when they appear to continue with the testing of rest of the application.
Is there a way of getting the handles to these dialogs as and when they open up. And, can we close these dialogs using those handles.

We do not have any access to the source code of the application that we are testing.

Thanks,
Madhavi

NoHero
December 21st, 2004, 08:34 AM
At first you should differ if these dialos are opened modal or not. Searching modal dialogs is much easier because you just recieve the top window. If a non modal window is open and it can be in the background too. Just take a look around in this forum and you will find many threads showing ways to find windows. One possible thread is this one (http://www.codeguru.com/forum/showthread.php?t=310015).

Arjay
December 21st, 2004, 04:45 PM
During this process, some unwanted and erroneous dialogs of the tested application will remain open. (we will not have any information on these dialogs.)I have a few questions:
1) Why won't you have any information? Can't you use spy to retrieve the title and class name of these dialogs?
2) >> ...will remain open. What do you mean by this? How do these dialogs 'remain open?' Can you determine what causes these dialogs to appear?

I'm asking because the techniques used to handle these dialogs vary depending on how you answer.

Arjay

MadhavitRao
December 24th, 2004, 06:36 AM
Hi,

At first you should differ if these dialos are opened modal or not. Searching modal dialogs is much easier because you just recieve the top window. If a non modal window is open and it can be in the background too. Just take a look around in this forum and you will find many threads showing ways to find windows. One possible thread is this one (http://www.codeguru.com/forum/showthread.php?t=310015).

Basically, we are not bothered abt the modalness of the dialog. We would just close them by sending WM_CLOSE message to the dialog. Our basic problem is determining the handle of the dialog as soon as they appear.

I have a few questions:
1) Why won't you have any information? Can't you use spy to retrieve the title and class name of these dialogs?
2) >> ...will remain open. What do you mean by this? How do these dialogs 'remain open?' Can you determine what causes these dialogs to appear?

I'm asking because the techniques used to handle these dialogs vary depending on how you answer.

Arjay


We can't use spy to retrieve the information, Coz these dialogs will appear randomly at runtime.

And these dialogs MAY remain open due to some bugs in the application that we are testing. And we do not want to stop the whole process of testing just because of one erroneous dialog. We want to log this error and continue with testing of the rest of the UI.

The solution that we have thought is....

1) We should get the handle of any dialog that pops up, as and when they appear.
2) Once we get the handle of a dialog we will store this handle in a buffer.
3) After the testing of this particular part of UI, we will confirm that all these handles are closed.
4) If they are not closed then, we will close them by sending WM_CLOSE message.

Now the problems that we are facing are....
1) how do we get the handle of the dialog as soon as they appear?
2) And when a dialog is closed, how do we get to know the handle that it was holding?


Also, Is there a way of getting the handles of all the dialogs/windows that are open at a given point of time.

NoHero
December 24th, 2004, 06:43 AM
Since they can pop at any random time. You should start an own worker thread just handling any possible pop ups. Your solution might face some problems: the handle to window changes every time the application creates it. A window does not have the same HWND everytime it gets created. So you should use Spy++ to determinate the class of the windows and or it's titles and then search them - as said in a worker thread - with FindWindow(). FindWindow() allows you to search a window with specified title and/or classname. If FindWindow() returns a valid HWND you should close the window. That's how I would save it. But you should permantently check if one of the pop-ups is shown.

rupeshshukla
December 24th, 2004, 08:40 AM
Since they can pop at any random time. You should start an own worker thread just handling any possible pop ups. Your solution might face some problems: the handle to window changes every time the application creates it. A window does not have the same HWND everytime it gets created. So you should use Spy++ to determinate the class of the windows and or it's titles and then search them - as said in a worker thread - with FindWindow(). FindWindow() allows you to search a window with specified title and/or classname. If FindWindow() returns a valid HWND you should close the window. That's how I would save it. But you should permantently check if one of the pop-ups is shown.

if u r using atl u can do it by simple calling by one function
::DestroyWindow(m_hWnd);
where m_hWnd is the handle of currently running application
and it is provided by window itself
if u wann u can read CWindow

& CWindowImpl for more ingormation

and in case of modeless
just call GetActiveWindow() function
and u r going to get the handle of your currently running application and watever u wann u can do with that application

NoHero
December 24th, 2004, 01:20 PM
if u r using atl

At first we are here in the WinAPI forum
Second: You mean the MFC (better WTL). Because ATL is the active template library, thats a completly different story.


u can do it by simple calling by one function
::DestroyWindow(m_hWnd);
where m_hWnd is the handle of currently running application
and it is provided by window itself
if u wann u can read CWindow

With this you only free your own handle. That doesn't mean the the window gets closed. DestroyWindow() only frees the internal memory allocated by creating the window.


and in case of modeless
just call GetActiveWindow() function
and u r going to get the handle of your currently running application and watever u wann u can do with that application


The return value is the handle to the active window attached to the calling thread's message queue. Otherwise, the return value is NULL.


Found at this MSDN article. (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/getactivewindow.asp).
So you will only retrieve the current window you created. But not a window that was created by another application.

Arjay
December 24th, 2004, 09:11 PM
We can't use spy to retrieve the information, Coz these dialogs will appear randomly at runtime.

And these dialogs MAY remain open due to some bugs in the application that we are testing. And we do not want to stop the whole process of testing just because of one erroneous dialog. We want to log this error and continue with testing of the rest of the UI.The idea of attempting to continue testing has merit but it may be difficult to achieve in practice.

This is because if the dialog is modal, the application will not continue to run until the dialog has been dismissed. I assume that your automation causes some action to happen (say "File\Open") and verifies that the action has occurred? If an unexpected modal dialog appears, then the file dialog will not ever show up.

Your automation should be written such that it catches this error (i.e. the open dlg never appears).

I don't think you can really handle these unexpected dialogs as you mentioned but I believe you can capture their data so these can be added to the automation the next time your automation is run.

You can do this by:
1) Create a stack trace of your automation (i.e., log file)
2) Snap a screen shot when your automation intercepts an error (a dlg didn't appear)
3) Get the class and title of the foreground window

Using this info, you can alter your automation to account for the dialogs in the future.

I've done quite a bit of automation in the past and I'm puzzled as to why these random popups appear in the application. To me, if the automation is performing an action and some unexpected dialog appears, isn't this a bug? If this isn't the case, could you give an example of what these popups are or could be?

The point to running your automation is to catch bugs. I've read your response regarding capturing the handles and closing any unclosed dialogs. However, I believe this will mask bugs.

So one strategy to keep the automation running is to break your automation up into small areas.

So rather than running one large automation script (doesn't have to be a script per se, it could be an exe), run several scripts each testing a portion of the app.

Part of successful automation is the ability to repro the problem, so this is why I'm suggesting an alternative. It doesn't do anyone much good if you are encountering unexpected dialogs and are dismissing them with some 'magical' method. IMO, you are better off, by intercepting the error, capturing the info (for a good repro), closing the app and fire up the next automation script.

Arjay

MadhavitRao
December 26th, 2004, 03:14 AM
I've done quite a bit of automation in the past and I'm puzzled as to why these random popups appear in the application. To me, if the automation is performing an action and some unexpected dialog appears, isn't this a bug? If this isn't the case, could you give an example of what these popups are or could be?
Arjay

The random dialogs that open up need not always be because of some bugs in the application that we are testing, it can some times be because of the scripts that we write.

And every failure in testing process and bugs found in the applications are loged. So we are not masking any bugs.

We can have two kinds of failure....
1) Bugs in the application.
2) Failure in successful excecution of the testing scripts themself.

Our aim is to minimize the problems that fall in the 2nd category.
The scripts are effecient enough to find out the bugs in the application, IF the scripts run SUCCESSFULLY. So our aim, at the first place, is to make the scripts run successfully. (i.e to write scripts that are intellegent enough to recover from any failures.)

If we have an unexpected dialog open, because of some bug in the application,
this is anywayz logged in the application bugs log. But due to this dialog that is not closed all the scripts that follow this one will fail (under the 2nd category which is not fair.)

And it is impossible to keep track of all the dailogs that can appear because they are thousands of them and we cannot say that they will always appear. They appear sporadically. For example, we may have some dialogs that appear when there is a security breach and many more things like that. These will not happen always. And our aim is to get them when they occur and take corrective actions so the the failure doesn't creep into the following test scripts. (we will have thousands of scripts running one after the other at a stretch)

Quoting an understandable example would be a little difficult coz i'll have to explain the whole application. Just to quote a simple one....
If two users or process are using same object and they are trying to change it then, a dialog pops up saying, "the object is in use". This is not a bug in the application. But we will have to close this dialog before proceeding to the next script so that the next script doesn't fail because of this dialog that it should not even care for.

The solution that we are thinking is like this..... we should get a notification for every dialog that pops up. And as the part of post codition of our script, we will check if this dialog is closed. If it is not, we should close them.

(OR)

We should get the handles of all the dialogs that are open in that system before the start of the script and at the end of the script(as the part of precondition and postCondition of a test script) If there are any excess handles in the postcondition we should close that dialog.

Now our problem is how to get a notification when a dialg appears
(OR)
How to get the handles to open dialog at any give time.

Arjay
December 27th, 2004, 04:53 PM
But due to this dialog that is not closed all the scripts that follow this one will fail (under the 2nd category which is not fair.)I understand you are trying to dismiss extraneous dialogs which may appear when an application failure has occurred in order that subsequent scripts don't fail. But I have to wonder if this is really the correct thing to do. Because, even if you are able to dismiss the dialogs, how can you be sure the internal state of the application is left in a stable condition?

I'm a firm believer in controlling the environment and getting the application back to some known good state after an error has occurred.

Before we talk about a couple of env control strategies (and answers to your questions below) let's look at two main methods for executing test automation:

Method 1 - Dependent scripts. Leave the application open while running subsequent scripts. This method usually has the first script in the sequence launch the application, followed by several other 'functionality' scripts, and finally the last script closes the application.
Method 2 - Independent scripts. Each script launches the application, performs app initialization (gets the UI in some known state like fullscreen w/docking windows closed), performs the functionality testing, then closes the app.
The main benefit of method 1 is speed since it takes some time to launch and close the application (compare launching and closing the app once for a series of scripts vs. launching and closing the app for each script). Method 2 is willing to sacrifice speed for robustness. Because each script is independent, each script is responsible for launching and closing the app, and getting it into some known state.

I prefer method 2 because, in the long run, it's easier to have each script independent of each other. Clean up is simpler, you can change the run order of the scripts, and you don't have to worry about a failed script poluting subsequent scripts.

Now onto the clean up strategies... I've found that there are only really two ways you can clean up the environment after an error has occurred:

Close the app
Reboot/Restart the system
I generally use the 'close the app' method when a non-catastrophic error has occurred such as a window that didn't appear at the correct time. I use the 'reboot the system' method when something major has occurred in the application such as a GPF. Of course, you have to have a somewhat smart test harness that is capable of rebooting the system, logging on, and continuing the test pass (running the next script or app in the sequence).

This type of cleanup strategy has serve me well, but it seems that we don't agree on the importance of a clean environment (and that's okay of course).

The solution that we are thinking is like this..... we should get a notification for every dialog that pops up. And as the part of post codition of our script, we will check if this dialog is closed. If it is not, we should close them.

(OR)
You can get the dialog creation notification by using a windows hook (see SetWindowsHookEx - CBTProc in msdn).
We should get the handles of all the dialogs that are open in that system before the start of the script and at the end of the script(as the part of precondition and postCondition of a test script) If there are any excess handles in the postcondition we should close that dialog.

Now our problem is how to get a notification when a dialg appears

You can capture existing dialogs with EnumWindows/EnumChildWindows and use the hook above for application specific dialogs.

(OR)
How to get the handles to open dialog at any give time.Use EnumWindows to retrieve the open windows or dialogs.

Lastly, one simple method that doesn't use any of the above, is to simply send a series of ESC keys to the application before closing it. Usually this will cancel any open application dialogs. To do this, call SendInput in a loop passing the appropriate ESC key with a slight pause in between.

Good luck.

Arjay