I am programming a .NET Framework application that open a website in Chrome and change it to full screen.
The problem I am facing is to determine if the web is already open (I don't want to open multiple pages unnecessary), In that case the program should just switch the current active window to the correct tab and switch to full screen.
The problem is only the active tab is visible to the C# program at a time, so the program needs to check each tab manually (by switching the active tab and check is title).
I don't care if the screen is flickering throw all the tabs.
I found this solution online:
private void GetCaptionOfActiveWindow()
{
Process[] procs = Process.GetProcessesByName("Chrome");
// to find the tabs we first need to locate something reliable - the 'New Tab' button
if (procs.Length == 0)
{
//some code to open chrome with the correct web site and change to full screen
return;
}
IntPtr hWnd = IntPtr.Zero;
int id = 0;
int numTabs = procs.Length;
foreach (Process p in procs)
{
if (p.MainWindowTitle.Length > 0)
{
hWnd = p.MainWindowHandle;
id = p.Id;
break;
}
}
SetForegroundWindow(hWnd);
SendKeys.SendWait("^1"); // change focus to first tab
Thread.Sleep(100);
int next = 1;
string title;
while (next <= numTabs)
{
try
{
title = Process.GetProcessById(id).MainWindowTitle.Replace(" - Google Chrome", "");
//richTextBox1.Text += title + "\n";
if (title.ToLower().Contains("some web site name"))
{
// some code to change the current active tab and change to full screen.
return;
}
next++;
SendKeys.SendWait("^{TAB}"); // change focus to next tab
Thread.Sleep(100);
}
catch (Exception ex)
{
// Chrome internal process, doesn't have tab.
}
}
//richTextBox1.Text += "web not exists\n";
//some code to open new tab with the correct web site and change to full screen
}
This solution works fine if all the Chrome tabs are open in the same window.
My problem is to figure out what to do if the tabs are scatterd across multiple Chrome Windows.
Related
I have created WinForm application which has webBrowser control docked with Fill property and redirects the user to the URL user provides.I am executing the winForm process from chrome Extension and getting the handle of chrome and changing the parent of my child process(WinForm) to chrome browser process.
I am losing the focus when I Minimize the chrome and restore again.
But on switching the tab or either from Alt+Tab to locate my winForm .exe the focus comes back.
How to set the focus of my .exe whenever the user comes to my active tab.
I have written the application in C# and used the Unmanaged code SetParent(child handle, parent handle) API to attach my .exe.
Some links I already tried :
https://www.codeproject.com/Articles/101367/Code-to-Host-a-Third-Party-Application-in-our-Proc
Docking Window inside another Window
Hosting external app in WPF window
Code Snippet :
Listening the below C# code snippet in a thread in an infinite while loop to get the messages from my main.js
private void SetAsParent()
{
try
{
Process[] p = Process.GetProcessesByName("chrome");
foreach (Process item in p)
{
if (!String.IsNullOrEmpty(item.MainWindowTitle))
{
if (item.MainWindowTitle.Contains("Some Title to match my condition to show the exe...."))
{
this.Top = 78;
this.Left = 0;
SetParent(this.Handle, item.MainWindowHandle);
this.Visible = true;
this.Show();
this.Focus();
webBrowser.Navigate(some URL);
webBrowser.Size = new Size(1366, 979);//dynamic values coming from chrome main.js message via postMessage()
}
}
else
{
this.Hide();
}
}
this.Size = new Size(1366, 979);
}
catch (Exception ex)
{
Debug.WriteLine("Inside Form Load : {0}", ex.Message.ToString());
}
}
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
Chrome Extenion main.js :
chrome.windows.onFocusChanged.addListener(function() {
chrome.windows.getCurrent(function(window){
console.log(window.state);
if(window.state == "normal")
{
Some message to port...
}
else if(window.state == "maximized")
{
Focus message to port...
}
else if(window.state == "minimized")
{
Minimised message to port....
}
});
});
Expected Output :
On switching the tab the focus is retained but on minimizing and restored the focus is lost.
I want to open a new tab and close the first one in Selenium.
So, I was using the SendKeys method to do this.
But my problem is when I open the new tab, I can't continue using the SendKeys method to switch to my first tab and close the current one.
When entering the while loop, both SendKeys and ExecuteJS are not working.
I tried using this javascript code:
browser.ExecuteJS("window.close();");
but it is also not working.
My code is like this:
IWebElement body = browser.FindElementByTagName("body");
//browser.ExecuteJS("window.open();");
body.SendKeys(OpenQA.Selenium.Keys.Control + 't');
browser.DeleteAllCookies();
Thread.Sleep(50);
while (browser.GetWindowNum() > 1)
{
body.SendKeys(OpenQA.Selenium.Keys.Control + OpenQA.Selenium.Keys.Tab);
body.SendKeys(OpenQA.Selenium.Keys.Control + 'w');
//browser.ExecuteJS("window.close();");
_tmExcute = DateTime.Now;
}
browser.GoToUrl(link);
browser.WaitForPageToLoad();
I use the method GetWindowNum() to check if the number of tabs is more than 1.
Here is my code to check the number of tabs in the browser:
public int GetWindowNum()
{
return wd.WindowHandles.Count;
}
You can simply switch the first window and close it using the driver and WindowHandles
ReadOnlyCollection<string> windowHandles = wd.WindowHandles;
string firstWindow = windowHandles.ElementAt(0); //first window handle at 0 index
foreach (string handle in windowHandles) { //Gets the new window handle
if(handle == firstWindow) {
wd.switchTo().window(handle); // switch focus of WebDriver to the first window
wd.close(); //close that window
break;
}
}
There is a full screen Windows POS Application(Aloha), that contains button, which opens a Windows form. The Form is set to be TopMost=true, ShowIcon = false and ShowInTaskbar = false. Once the button pressed, POS stays open full screen on top of Taskbar with a form above it.
If the form is closed\out of focus, its process exits and everything stays the same. But if button pressed while the form is open, it kills another instances of itself and then Taskbar pops-up on top of POS(once other instances are killed).
KillRunningProcess Function
private void KillRunningProccess()
{
try
{
Process[] proc = System.Diagnostics.Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location));
Process currentProcess = Process.GetCurrentProcess();
if (proc != null)
{
foreach (Process currProc in proc)
{
if (currentProcess.Id != currProc.Id)
{
currProc.Kill();
}
}
}
}
catch
{ }
}
I've tried using different PINVOKE API functions on Shown\GotFocus events, without any success. Hiding the taskbar fully is out of the question.
I'm recording Coded UI Tests with VS 2012, which shall test the functions of a web application.
After I loaded the web page, I click on a button to start p.e. a job application.
After the next page has loaded on the same site, my problem begins.
The entry controls are at the end of the web site.
To take a look and input data into the entry controls, I must scroll down.
The recording produced the following method in the UIMap.
Designer.cs:
public void Scrollen()
{
#region Variable Declarations
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.AllThreads;
this.UIGoogleMozillaFirefoxWindow.UIItemPropertyPage.UIBewerbungDemoFirmaDocument.WaitForControlExist();
this.UIGoogleMozillaFirefoxWindow.UIItemPropertyPage.UIBewerbungDemoFirmaDocument.WaitForControlReady();
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.UIThreadOnly;
WinControl uIBewerbungDemoFirmaDocument = this.UIGoogleMozillaFirefoxWindow.UIItemPropertyPage.UIBewerbungDemoFirmaDocument;
#endregion
// Click "Job application" document
Point pt = new Point(1390, 553);
int count = 0;
while (!uIBewerbungDemoFirmaDocument.TryGetClickablePoint(out pt) && count < 20)
{
count++;
System.Threading.Thread.Sleep(10);
if (count == 20)
Console.WriteLine("ClickablePoint not found");
}
Mouse.Click(uIBewerbungDemoFirmaDocument, new Point(1390, 553));
Mouse.MoveScrollWheel(10);
}
As You can see, I tried WaitForControlExist, WaitForControlReady, TryGetClickablePoint and the method MoveScrollWheel.
But neither Mouse.Click nor Mouse.MoveScrollWheel are working.
And in the next method, where I click into the first of the entry fields, I get a message at execution time, that the click event produces an error, because the control is hidden (because it's down below on the website, out of visible range).
After several tests this is making me crazy.
Any idea what has gone wrong and how can I scroll down the web site, so my entry controls are in visible range?
You can try Control.EnsureClickable(). Or you can use below mentioned function to scroll the page until the control is not clickable.
public static void ScrollAndClick(HtmlControl Control)
{
bool isClickable = false;
if (Control.TryFind())
{
while (!isClickable)
{
try
{
Control.EnsureClickable();
Mouse.Click(Control);
isClickable = true;
}
catch (FailedToPerformActionOnHiddenControlException)
{
Mouse.MoveScrollWheel(-1);
throw;
}
}
}
else
{
throw new AssertInconclusiveException("Control Not Found");
}
}
You can also add condition related to timeout to make sure it don't go to infinite loop.
Let me know if you are having issue with this at your end.
This is web single sign on code that runs on a .net 3.5 winform. The code runs fine for ie6 or ie8 as long as ie8 only has one tab open. The problem is that if the user opens a new tab (tab 2,3,etc.) and navigates to a web site (web form internal in the organization) the below code will be executed but the ie COM automation object will return the HTMLDocument for the first tab (Tab 1) even though tab 2 is the active tab. I can't find any IE tab references in the InternetExplorer or HTMLDocument classes anywhere. Actually, there's very little IE tab related documentation anywherer in the IE COM automation docs.
AutoResetEvent ie2_NavigateCompleteAutoReset;
/// <summary>
/// Given the handle of an Internet Explorer instance, this method performs single sign on to
/// several known web login forms.
/// </summary>
/// <param name="iEFramHandle"></param>
private void WebFormSignOn(int iEFramHandle)
{
foreach (SHDocVw.InternetExplorer ie2 in new SHDocVw.ShellWindows())
{
if (ie2.HWND == iEFramHandle)
{
while (true)
{
Thread.Sleep(100);
if (ie2.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
try
{
mshtml.HTMLDocument doc = (mshtml.HTMLDocument)ie2.Document;
ie2.NavigateComplete2 += new SHDocVw.DWebBrowserEvents2_NavigateComplete2EventHandler(ie2_NavigateComplete2);
ie2_NavigateCompleteAutoReset = new AutoResetEvent(false);
/*Find the username element and enter the user's username*/
mshtml.HTMLInputElement userID = (mshtml.HTMLInputElement)doc.all.item("username", 0);
userID.value = Globals.Username;
/*Find the password element and enter the user's password*/
mshtml.HTMLInputElement pwd = (mshtml.HTMLInputElement)doc.all.item("password", 0);
pwd.value = Globals.GetAppName();
/*Find the submit element/button and click it*/
mshtml.HTMLInputElement btnsubmit = (mshtml.HTMLInputElement)doc.all.item("submit", 0);
btnsubmit.click();
/*Wait up to 5 seconds for the form submit to complete.
This is to prevent this method from being called multiple times
while waiting for the form submit and subsequent navigation from completing.*/
ie2_NavigateCompleteAutoReset.WaitOne(5000);
return;
}
catch (Exception err)
{
Logger.Log(err.ToString(), Logger.StatusFlag.Error, this.ToString(), "WebFormSignOn");
return;
}
finally
{
/*Remove the event handler*/
ie2.NavigateComplete2 -= ie2_NavigateComplete2;
}
}
}
}
}
}
void ie2_NavigateComplete2(object pDisp, ref object URL)
{
ie2_NavigateCompleteAutoReset.Set();
}
It turns out that each tab in IE 8 has it's own process and handle. In the original code i was always getting the handle from the first IEFrame. I modified the code (below) and now it works. The change is that instead of looking for just the first IEFrame handle, the code also looks for a LocationURL that matches the url that triggerd the method that calls WebFormsSignOut.
private void WebFormSignOn(int iEFramHandle,string addressBarText)
{
var shellWindows = new SHDocVw.ShellWindows();
foreach (SHDocVw.InternetExplorer ie2 in shellWindows)
{
if (ie2.LocationURL==addressBarText)
{ //rest of the code (see orignal post)
Internet Explorer does not have any public tab APIs (beyond allowing you to target a navigation to a new foreground or background tab). Each ActiveX control or BHO is loaded individually into an individual tab instance. Trying to walk down from the ShellWindows collection isn't likely to work in general, instead you should have your plugin reach out to its hosting site (e.g. IObjectWithSite::SetSite will convey this info) which will allow you to determine your hosting tab.