获取已打开的Chrome浏览器的WebDriver

时间:2018-02-28 10:27:28

标签: c# selenium selenium-chromedriver

我想要一个已经打开过的浏览器的IWebDriver,比如Chrome。因为那时我需要自动化表单身份验证和/或基本身份验证。

我以为这个

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

可以做到这一点,但它只打开另一个镀铬窗口。相反,我想"阅读"一个已经开放的。

硒有可能吗?我应该使用另一个图书馆吗?

1 个答案:

答案 0 :(得分:2)

根据Selenium Issues页面: https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/18

该问题已结束并标记为不可行 连接到现有浏览器的过程将基于每个浏览器。 在IE中进行操作可能很简单,但在Chrome或Firefox中进行操作会有问题。

例如: Chrome实际上通过网络/ tcp json请求从Selenium接收命令到特定端口。 当Selenium驱动程序停止运行时 - 它会丢失Chrome调试端口的端口号。 端口可能仍然是打开的,但它可以是10000到30000之间的任何东西

即使您为Chrome解决了这个问题,也需要另外一个针对Firefox的定制解决方案。

除非您的身份验证包含“验证码”。或bot检查到位,我建议只是自动化身份验证阶段。 一般来说 - 自动化测试是独立的,不依赖于外部干扰或外部测试,这是一种很好的做法。

浏览器应该在测试开始时开始,并在测试结束时终止。

假设您使用Selenium进行测试而非恶意目的。

Selenium在这个阶段对你没有帮助。

但是,如果您的答案/解决方案可以在Chrome上使用,而不是其他浏览器。

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;
            }
        }

这将启动一个chrome进程,调试端口打开到您提供的数字。  (您可以跟踪此情况,并重新连接并向正在运行的chrome实例重新发出命令)

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);
        }

这是我躺在的一些代码。 有一天我很无聊,决定用Chrome自动化重新发明轮子。基本上 - 这段代码就是如何在不使用Selenium的情况下自动化Chrome。 它确实依赖于WebSockets4Net 但话虽如此 - 可能会重构使用TcpClient。 发给Chrome的所有命令都以json请求的形式完成。

例如:以下json命令会告诉chrome执行以下javascript - 基本上导航到提供的URL。

{
    "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;
        }

为了演示如何实际使用它 - 您可以实现页面对象并创建'类型'将对象封装在屏幕上。

例如:

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;
        }
    }

警告 - 当我使用此代码时,WebSockets4Net中存在内存泄漏 - 因此最终必须重新启动应用程序。 也许如果WebSockets4Net被删除和替换 - 它会更好。