C# Selenium check if browser is active/focus

Viewed 764

i need to send some key inputs to different browser sessions and want to make sure the right session is active.

i used this method, which is actually working.

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

[DllImport("User32.dll")]
private static extern IntPtr SetForegroundWindow(IntPtr hWnd);

driver = new ChromeDriver()
IntPtr browserWriteTarget1 = GetForegroundWindow();
driver = new ChromeDriver()
IntPtr browserWriteTarget2 = GetForegroundWindow();
driver = new ChromeDriver()
IntPtr browserWriteTarget3 = GetForegroundWindow();

SetForegroundWindow(browserWriteTarget1);

if (browserWriteTarget1 == GetForegroundWindow()
                {
                    SendKeys.SendWait($"{myKey}");
                    Thread.Sleep(tWait);
                }

The problem is if the user clicks around, while driver = new ChromeDriver is loading, that IntPtr browserWriteTarget = GetForegroundWindow(); will get the wrong value and the process will break.

The browser titles are all the same as im opening the same URL several times.

Is there a better solution, to avoid this?

2 Answers

Approach 1: Add a IJavascriptExecutor script

((IJavaScriptExecutor)driver).ExecuteScript("window.focus();");

By calling this statement in combination with the specific driver instance will give the newly opened chrome browser the focus.

Approach 2: Save a CurrentWindowHandle

        driver = new ChromeDriver(@"D:/Projects/Training/SeleniumApp/SeleniumApp/");
        string driverWindowHandle = driver.CurrentWindowHandle;

        driver_2 = new ChromeDriver(@"D:/Projects/Training/SeleniumApp/SeleniumApp/");
        string driver_2_WindowHandle = driver_2.CurrentWindowHandle;

        driver.Navigate().GoToUrl("https://www.google.com/");

        driver_2.Navigate().GoToUrl("https://www.bing.com/");

        driver.SwitchTo().Window(driverWindowHandle);

This method saves a handle of the window that's been opened through a specific driver instance. With this handle you can perform browser actions on a single browser. Use the code to see how this works and you'll find that clicking around will not influence the code's performance.

Sources

  1. Make sure that browser opened by webdriver is always in focus;
  2. Bring the Firefox Browser to Front using selenium Java (Mac OSX);

Get current running Processes and keep track of what is being added. And then you can just use that Handle without bothering what is actually showing on the Foreground.

using System.Diagnostics;
using System.Linq;
...
// First Get current running processes. Filter them by the ProcessName.
var myProcesses = Process.GetProcesses()
   .Where(p => p.ProcessName.Equals("MyProcess", StringComparison.OrdinalIgnoreCase))
   .ToList();

// Launch Chrome
driver = new ChromeDriver();

// You might want to add some wait, and confirm if the Processes are increasing before
// for ex:
while(Process.GetProcesses()
   .Where(p => p.ProcessName.Equals("MyProcess", StringComparison.OrdinalIgnoreCase))
   .Count() == myProcesses.Count + 1)
{
    Thread.Sleep(1000); // wait a second
    // you may also put some timeout, so we are not in this loop forever, in case of some error.
}  

// Get Current running process again.
var newProcesses = Process.GetProcesses()
   .Where(p => p.ProcessName.Equals("MyProcess", StringComparison.OrdinalIgnoreCase))
   .ToList();

foreach(var process in myProcesses)
{
    // Remove the old processes.
    newProcesses.Remove(process);
}

// Get the Handle of the only remaining process
IntPtr browserWriteTarget1 = processes.First().Handle;

// repeat to the next one
Related