1

I would like to have a IWebDriver of an already opened browser like Chrome. Because then I need to automate a form authentication and/or a basic authentication.

I thought that this

IWebDriver driver = new RemoteWebDriver(new System.Uri("http://localhost:4445/wd/hub"), new ChromeOptions());

would do the trick but it only opens another chrome window. Instead I would like to "read" an already opened one.

Is it possible with selenium? O r should I use another library?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
ayasha
  • 1,221
  • 5
  • 27
  • 46
  • Possible duplicate of [How can I reconnect to the browser opened by webdriver with selenium?](https://stackoverflow.com/questions/47861813/how-can-i-reconnect-to-the-browser-opened-by-webdriver-with-selenium) – undetected Selenium Feb 28 '18 at 11:18

1 Answers1

3

As per the Selenium Issues page: https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/18

The issue was closed and marked as not feasible The process of connecting to an existing browser would be on a per-browser basis. Doing it in IE might be easy, but doing it in Chrome or Firefox would be problematic.

Eg: Chrome actually receives the commands from Selenium via network / tcp json requests to a specific port. When Selenium driver stops running - it loses the port number for the Chrome debugging port. The port may still be open, but it could be anything between 10000 and 30000 etc

Even if you solve it for Chrome, it would then require another bespoke solution for Firefox.

Unless your authentication has a 'Captcha' or bot check in place, I would suggest just automating the authentication stage. Generally speaking - it is a good practice for Automated tests to be self-contained and not rely on outside interference or external tests.

A browser should start at the start of the test and be terminated at the end of the test.

Assuming you are using Selenium for testing and not for malicious purposes.

Selenium will not be helpful to you at this stage.

If however, you can live with your answer / solution being on Chrome but not the other browsers.

public static Chrome StartChromeDriver(int port)
        {
            try
            {
                string Path = Registry.Installation.GetChromeExecutable();
                Process p = new Process();
                ProcessStartInfo psi = new ProcessStartInfo(Path);
                string args = "--remote-debugging-port="+ port.ToString()+" --user-data-dir=remote-profile";
                psi.Arguments = args;
                psi.Verb = "runas";
                p.StartInfo = psi;

                p.Start();

                return new Chrome("http://localhost:" + port.ToString());
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.ToString());
                return null;
            }
        }

This will start a chrome process with the debugging port opened to the number you provide. (You can keep track of this, and reconnect and re-issue commands to the running chrome instance)

public dynamic EnablePage()
        {
           json = @"{""id"":12345,""method"":""Page.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }
        public dynamic EnableRuntime()
        {
            json = @"{""id"":12345,""method"":""Runtime.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }
        public dynamic EnableNetwork()
        {
            json = @"{""id"":12345,""method"":""Network.enable""}";
            Thread.Sleep(1000);
            return this.SendCommand(json);
        }

This is some code I had lying around. I was very bored one day and decided to reinvent the wheel with Chrome automation. Basically - this code is how you could automate Chrome without using Selenium at all. It does have a dependency on WebSockets4Net But that being said - it could probably be refactored to use TcpClient. All the commands that are issued to Chrome, are done in the form of a json request.

Eg: the following json command would tell chrome to execute the following javascript - essentially navigating to the url provided.

{
    "method": "Runtime.evaluate",
    "params": {
        "expression": "document.location='urlhere'",
        "objectGroup": "console",
        "includeCommandLineAPI": true,
        "doNotPauseOnExceptions": false,
        "returnByValue": false
    },
    "id": 1
}


public dynamic SendCommand(string cmd)
        {
            if (EventHandler == null)
            {
                EventHandler = new Events();
                EventHandler.OnNavigateStart += new Events.OnPageNavigateStart(EventHandler_OnNavigateStart);
                EventHandler.OnNavigateEnd += new Events.OnPageNavigateEnded(EventHandler_OnNavigateEnd);
            }
            WebSocket4Net.WebSocket j = new WebSocket4Net.WebSocket(this.sessionWSEndpoint);
            ManualResetEvent waitEvent = new ManualResetEvent(false);
            ManualResetEvent closedEvent = new ManualResetEvent(false);
            dynamic message = null;
            byte[] data;

            Exception exc = null;
            j.Opened += delegate(System.Object o, EventArgs e)
            {
                j.Send(cmd);
            };

            j.MessageReceived += delegate(System.Object o, WebSocket4Net.MessageReceivedEventArgs e)
            {
                message = e.Message;
                EventHandler.ParseEvents(e);
                waitEvent.Set();

            };

            j.Error += delegate(System.Object o, SuperSocket.ClientEngine.ErrorEventArgs e)
            {
                exc = e.Exception;
                waitEvent.Set();
            };

            j.Closed += delegate(System.Object o, EventArgs e)
            {
                closedEvent.Set();
            };

            j.DataReceived += delegate(object sender, WebSocket4Net.DataReceivedEventArgs e)
            {
                data = e.Data;
                waitEvent.Set();
            };

            j.Open();

            waitEvent.WaitOne();
            if (j.State == WebSocket4Net.WebSocketState.Open)
            {
                j.Close();
                closedEvent.WaitOne();
                j = null;
            }

            if (exc != null)
                throw exc;
            serializer = null;
            serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new[] { converter });

            dynamic obj = serializer.Deserialize(message, typeof(object));
            message = null;
            data = null;
            return obj;
        }

To demonstrate how this could be used practically - you can implement page-object and create 'types' that encapsulate objects on screen.

For instance:

public class Link : Base.Element
    {
        public Link(string XPath)
        {
            this.XPath = String.Copy(XPath);
        }

        /// <summary>
        /// Overriding it - just in case we need to handle clicks differently
        /// </summary>
        /// <returns></returns>
        public virtual bool Click()
        {

            Sync();
            Console.WriteLine(Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).click();"));
            return true;
        }

        public virtual bool WaitForExistance(int iTimeout)
        {
            return base.WaitForExistance(iTimeout);
        }

        public virtual bool Exists()
        {

            return base.Exists();
        }


        public virtual string GetText()
        {
            Sync();
            dynamic dval =  Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).innerText");
            return dval.result.result.value;
        }
    }

Be warned - there were memory leaks in WebSockets4Net when I was using this code - so the application eventually had to be restarted. Perhaps if WebSockets4Net is removed and replaced - it will work better.

Baaleos
  • 1,703
  • 12
  • 22
  • My company wants to automate the process of authentication so we need to do it both from already opened pages and when browser starts automatically. I will need to find another library then. Thanks. – ayasha Feb 28 '18 at 10:39
  • Is your authentication system so complex that Selenium cannot complete it? In any case- if you have your heart set on trying to accomplish this, I would suggest you make your problem bite-size. Can you live with the solution being on a single browser? If so - I would suggest looking at Chrome Automation via debugging protocol. – Baaleos Feb 28 '18 at 11:47
  • I've added some code that I had lying around- basically in the past, I developed my own automation code for Chrome that worked completely devoid of Selenium. This would allow you to reconnect to an existing Chrome window - assuming the window was opened with the debugging port being open. – Baaleos Feb 28 '18 at 12:02
  • the problem is not authenticate the problem is identify already opnened chrome browsers. I will try your solution, thanks – ayasha Feb 28 '18 at 14:39