Order of WindowHandles - c#

I'm encountering an issue where WebDriver seems to change the order of WindowHandles. This causes us to close the wrong one intermittently after getting them in some cases.
What seems to happen is the previously established first window handle is returned as a subsequent handle, which causes my logic to of course, close the wrong one.
Is WebDriver supposed to return the window handles in the same order every time (order of first opened window to last?). This is what I initially expected, but now I'm not so sure.
I should also mention the problem seems to only occur in IE right now, but I'm not certain if this is a more generic issue.
Here is how I'm closing the active window and switching back to the root window.
public void Close()
{
//switch to latest window
string windowName = string.Empty;
if (_driver.WindowHandles.Count > 1)
{
//get 'root' window in list
windowName = _driver.WindowHandles[0];
_driver.Close();
_driver.SwitchTo().Window(windowName);
}
else
{
_driver.Close();
}
}
We're on WebDriver 2.45 (C# bindings, 32-bit IEDriver). If there is a method to close the active window in the C# bindings that would most likely solve this issue as well.

This pop up window handler is entirely unordered as per my understanding. I remember having same conversation on SO and luckily JimEvans(one of the contributors of Selenium) chimed in and clarify few factors. I read about the PopupWindowFinder of Selenium .NET bindings and found that class can make your life lot easier. API is here. However, the whole order issue is entirely complex and painful to deal with. See this thread. Just don't want to reinvent the wheel.

Related

Close IE specific window with C# using Kill is not working

I am trying to close the most recent window/tab of IE but when I call the Kill method the window relaunches without the content of the page.
This is the code that I use to get the most recent IE process:
var a = System.Diagnostics.Process.GetProcessesByName("iexplore");
DateTime earliestStart = DateTime.Today.Subtract(new TimeSpan(1,0,0,0));
System.Diagnostics.Process youngestProccess = a.FirstOrDefault();
foreach(var b in a){
if (b.StartTime > earliestStart)
{
earliestStart = b.StartTime;
youngestProccess = b;
}
}
youngestProccess.Kill();
The code is working in the way that the most recent window "stop" working but the window is not beeing closed
Any idea?
Hi I just discover how to solve the problem.
The message is being thrown because my IE has the option "Enable automatic crash recovery" checked in the Internet Options Advanced tab.
So if you face this you have 2 options: un-check that option forever (which might work for your case) or like in my case you can change the selection via registry keys and when you finish your testing return the value to be on.
So to do this you need to add this to your code before opening IE.
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Recovery", "AutoRecover", 2);
To turn back on the option you must do the same but with a 0
Registry.SetValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\Recovery", "AutoRecover", 0);

Faster way of searching for Top Level Windows in WPF CodedUI

I have several parts of my application that are supposed to close a window.
Checking that these windows have been closed using Coded-UI is incredibly slow. Right now my code looks like this:
Assert.IsFalse(UIMap.SomeWindow.TryFind(),
"X Window found when should be closed");
The problem is, this takes around 30s to search, and there are around 5 times this is used, and I have around 10 similar windows all being tested. I'd like to trim this time if possible, as it's making my tests slow.
I have also tried a dynamic solution (which is basically identical to the UIMap implementation):
var window = new WpfWindow();
window.SearchProperties.Add(UITestControl.PropertyNames.Name, "Window Title");
Assert.IsFalse(window.TryFind());
This is just as slow. It would be nice to use ApplicationUnderTest as a search parent, but as the window is Top Level, it doesn't seem to work.
Surely it shouldn't be too hard just to look at the open windows on my system (5), and check their titles against the search parameter?
Edit: Using SearchConfiguration.VisibleOnly doesn't seem to help either.
Found my answer, surprisingly on LinkedIn.
Now using:
Playback.PlaybackSettings.SearchTimeout = 1000; //in ms
Playback.PlaybackSettings.ShouldSearchFailFast = true;
Source: https://www.linkedin.com/grp/post/3828241-5843659258196959234
(C&P):
//Search Settings
// Value is in milliseconds. Default search timeout is 2 minutes.
// The search engine will continue making passes until the timeout has expired
// or the window has been found.
settings.SearchTimeout = 10000;
// Default search will make 3 attempts.
// If true the default 3 attempts is applied. If false then only one attempt should take place.
settings.ShouldSearchFailFast = true;
I think there might be a better answer. If set a global configuration like that and have to deal with a WPF Table and find a specific cell you might not find it working.
Using Window name generally isn't a great idea if there is any dynamic titles, Control Name is a good constant. It sounds to me like you are passing bad SearchProperties. You can use DrawHighlight() to see if CUI is actually finding your controls. First pass in the main parent window to your close window method, then use it as a try.
public static WinWindow _mainParent(string MainParentCtlName)
{
var _mainForm = new WinWindow();
_mainForm.SearchProperties.Add("ControlName", MainParentCtlName);
return _mainForm;
}
public static void CloseWindow(string MainWinCtlName)
{
var close = new WinButton(_mainParent(MainWinCtlName));
close.SearchProperties.Add("Name", "Close");
Mouse.Click(close);
}
try
{CloseWindow("MainWindowForm")}
catch{}

Balloon not showing up with NotifyIcon.ShowBalloonTip

I'm having trouble with something that I thought would be easy...
I can't get my NotifyIcon to show a balloon tip. The basic code is:
public void ShowSystrayBubble(string msg, int ms)
{
sysTrayIcon.Visible = true;
sysTrayIcon.ShowBalloonTip(20, "Title", "Text", ToolTipIcon.None);
}
Nothing happens when I execute this code. I read that the timeout arg may be in seconds or ms, can't tell, so I tried both and neither works.
I'm using WinXP, .NET 3.5.
I had foiled myself... This turned out to be an issue at the OS level. I had previously disabled all balloons via the registry a few weeks ago.
You can read the information here on how to disable balloon tips in WinXP:
http://support.microsoft.com/kb/307729
To enable them, just set the registry value to 1 instead and logon again/restart.
You should then log the messages for users who have disabled the balloons be able to go review them in case of need. If you can get permissions to read the registry, you could check the value and act accordingly (not to modify the value, but to log or to show the balloon).
Please see this it covers all combinations of mouse clicks with NotifyIcon as well as much more. The code is located in a template and is project setting driven so that you can implement NotifyIcon logic in all your projects with no coding effort at all.
More Here
http://code.msdn.microsoft.com/TheNotifyIconExample

What is the proper way of handling logoff / shutdown / restart when the application has unsaved data?

In WPF App.Current.SessionEnding must return in a few seconds, otherwise the "application does not respond" window appears. So the user can't be asked in this event handler to save his data, because the user's response takes longer than a few seconds.
I thought a solution would be to cancel the logoff / shutdown / restart, and resume it when the user answered to the file save dialog.
ReasonSessionEnding _reasonSessionEnding;
App.Current.SessionEnding +=
new SessionEndingCancelEventHandler(Current_SessionEnding);
void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
if (_dataModified)
{
e.Cancel = true;
_reasonSessionEnding = e.ReasonSessionEnding;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(EndSession));
}
}
void EndSession()
{
if (SaveWithConfirmation()) // if the user didn't press Cancel
//if (_reasonSessionEnding = ReasonSessionEnding.Logoff)
// logoff
//else
// shutdown or restart ?
}
The problem is that ReasonSessionEnding does not tell me if Windows was shutting down or restarting (it does not differentiate between the two).
So, what should my program do on the session ending event ?
Should it even do anything, or doing nothing on this event is the standard ?
The user is asked to save his changes in my main form's OnClosing method, so he does not lose data, but I think that the "application does not respond" window does not suggest a normal workflow.
Canceling the shutdown is not desired I guess, because some of the other programs have been shut down already.
What seems to be the accepted way is to display the save as dialog regardless.
Cancelling the shutdown, then resuming it later is most certainly not an option, for the reason you state and various others.
Since simply discarding the data is unacceptable, there really is no other options.
Well, except to save the data to a temporary file, then automatically restoring them the next time the program is run. Rather like MS Word after it has crashed. Actually, the more I consider it, the better it sounds.
Edit: There's yet another avenue, namely to save continously, the way eg. MS OneNote does. What has struck me before is that, provided you implement decent multilevel undo in your application, the whole manual saving business is actually somewhat dated - an anachronism from the days when disk operations were expensive and error-prone, nowadays mostly old habit.
But I'm digressing. Anyway, it's probably not applicable to your application, since I imagine it needs to be implemented from the beginning.

.NET (C#): Getting child windows when you only have a process handle or PID?

Kind of a special case problem:
I start a process with System.Diagnostics.Process.Start(..)
The process opens a splash screen -- this splash screen becomes the main window.
The splash screen closes and the 'real' UI is shown. The main window (splash screen) is now invalid.
I still have the Process object, and I can query its handle, module, etc. But the main window handle is now invalid.
I need to get the process's UI (or UI handle) at this point. Assume I cannot change the behavior of the process to make this any easier (or saner).
I have looked around online but I'll admit I didn't look for more than an hour. Seemed like it should be somewhat trivial :-(
If you don't mind using the Windows API, you could use EnumWindowsProc, and check each of the handles that that turns up using GetWindowThreadProcessId (to see that it's in your process), and then maybe IsWindowVisible, GetWindowCaption and GetWindowTextLength to determine which hWnd in your process is the one you want.
Though if you haven't used those functions before that approach will be a real pain, so hopefully there's a simpler way.
#ageektrapped is on the right track, however FindWindow will not search child windows.
For that you will need to use FindWindowEx
Thank you for your answers. Thanks to you here, I figured out how to know if the main window of a process is in front or not:
N.B : of course this needs System.Diagnostic and System.Runtime.Interrop
public bool IsWindowActive(Int32 PID)
{
return IsWindowActive(Process.GetProcessById(PID));
}
[DllImport("user32.dll")]
private static extern
IntPtr GetForegroundWindow();
public bool IsWindowActive(Process proc)
{
proc.Refresh();
return proc.MainWindowHandle.Equals(GetForegroundWindow());
}
You may find that if you call .Refresh() that you get the new top-level window.
If you know the window's title, you can use the Win32 call, FindWindow, through P/Invoke.
You can find the signature here on pinvoke.net
From what I understand MainWindowHandle property of the process you are starting is not valid. If that's the case, you can use FindWindow function (from Win32 SDK) which returns the window handle you need. All you need is the class name of target application's main window. You can obtain it using Spy++ or Winspector. You also need to ensure you have the right window by checking that window's process id using GetWindowThreadProcessId.
At last, I have to say I am not an expert on Win32 and there might be a better solution for your case.
Use Process.GetProcessById(proc.Id); where proc was your splash screen.
Works for me.
Now, how do you get to main window properties in System.Windows.Forms to give it focus w/o using win32?
After all .net is supposed to be a one-stop solution - is it not?
Somewhere in the code, the "real" main window is created. You can just save the window handle at that time and then after the splash screen closes you can set Application.MainWindow to the real window.
The MainWindowHandle property is cached after it is first accessed which is why you don't see it changing even after the handle becomes invalid. GregUzelac's information is correct. Calling Proces.Refresh will causes the next call to Process.MainWindowHandle to re-do the logic to find a new main window handle. Michael's logic also works because the new Process doesn't have a cached version of the MainWindowHandle.

Categories

Resources