使用 C# Selenium Webdriver 正确附加到现有 chrome driver

Properly Attach to existing chrome driver with C# Selenium Webdriver

我使用了 Tarun Lalwani 设计的 method 通过重用 C# 中的 url 和 sessionID 来附加 Selenium Chrome driver。此附件部分有效,但某些 driver 方法(例如 FindElement(By.ID) 显示错误 "invalid argument: invalid locator (Session info: chrome= 91.0.4472.114)" 这一行:

    var respBase = base.Execute(driverCommandToExecute, parameters);

我的猜测是,当 driver 为 attached.But 时,由于选项或所需功能为空,我还没有找到在 ReuseRemoteWebDriver 上正确设置它的方法。 附上外观的图片 driver here。 我该如何解决这个问题,以便我可以附加之前的 chrome driver 并保留所有预期的 selenium 功能?

 static void Main(string[] args)
        {

            InputSimulator teclado = new InputSimulator();
            ChromeOptions options = new ChromeOptions();
            options.UseSpecCompliantProtocol = true;
            ChromeDriverService service = ChromeDriverService.CreateDefaultService(@"Thepathofchromedriver");
            IWebDriver driver;
            DesiredCapabilities capabilities = new DesiredCapabilities();

            Uri myUri = new Uri("http://127.0.0.1:65431", UriKind.Absolute);
            service.Port = 65431;
            string ID = "1f42d5f0ad105910e8d2fc7be23480a9";
            if (ID != "")
            {
                
                IWebDriver drivertest1 = new ChromeDriver(service, options);
                
                IWebDriver drivertest = new ReuseRemoteWebDriver(myUri, ID,capabilities,options);
                driver = drivertest;
            }
            else
            {
                IWebDriver drivertest = new ChromeDriver(service,options);
                
                driver = drivertest;


            }

        IWebElement inputUser = driver.FindElement(By.Id("ID"));}


public class ReuseRemoteWebDriver : OpenQA.Selenium.Remote.RemoteWebDriver
    {
        private String _sessionId;
        
        public ReuseRemoteWebDriver(Uri remoteAddress, String sessionId, OpenQA.Selenium.Remote.DesiredCapabilities capability, ChromeOptions options)
            : base(remoteAddress,options)

        {
            this._sessionId = sessionId;
            var sessionIdBase = this.GetType()
                .BaseType
                .GetField("sessionId",
                          System.Reflection.BindingFlags.Instance |
                          System.Reflection.BindingFlags.NonPublic);
            sessionIdBase.SetValue(this, new OpenQA.Selenium.Remote.SessionId(sessionId));

            
        }

        protected override OpenQA.Selenium.Remote.Response
            Execute(string driverCommandToExecute, System.Collections.Generic.Dictionary<string, object> parameters)
        {
            if (driverCommandToExecute == OpenQA.Selenium.Remote.DriverCommand.NewSession)
            {
                var resp = new OpenQA.Selenium.Remote.Response();
                resp.Status = OpenQA.Selenium.WebDriverResult.Success;
                resp.SessionId = this._sessionId;
                resp.Value = new System.Collections.Generic.Dictionary<String, Object>();
                return resp;
            }
            var respBase = base.Execute(driverCommandToExecute, parameters);
            return respBase;
        }
    }

更新:正如我在回复中指出的那样,我可以解决大多数问题。 我无法恢复的最重要的功能是使用

注入 js 脚本
    IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    var script = "your script";
    js.ExecuteScript(script);

任何有关如何恢复注入脚本功能的想法都将不胜感激。

如果有人感兴趣,我将之前的 class 修改如下,这样我就可以使用 sendKeysToElement

    public class ReuseRemoteWebDriver : OpenQA.Selenium.Remote.RemoteWebDriver
    {
        private String _sessionId;

        public ReuseRemoteWebDriver(Uri remoteAddress, String sessionId, ChromeOptions options, ChromeDriverService service)
            : base(remoteAddress, options)

        {
            //object x = driver;
            this._sessionId = sessionId;

            var sessionIdBase = this.GetType()
                .BaseType
                .GetField("sessionId",
                          System.Reflection.BindingFlags.Instance |
                          System.Reflection.BindingFlags.NonPublic);


            //System.Collections.Generic.Dictionary<string, object> x = this.GetCapabilitiesDictionary(capability);


            sessionIdBase.SetValue(this, new OpenQA.Selenium.Remote.SessionId(sessionId));


        }

        protected override OpenQA.Selenium.Remote.Response
            Execute(string driverCommandToExecute, System.Collections.Generic.Dictionary<string, object> parameters)
        {
            if (driverCommandToExecute == OpenQA.Selenium.Remote.DriverCommand.NewSession)
            {
                var resp = new OpenQA.Selenium.Remote.Response();
                resp.Status = OpenQA.Selenium.WebDriverResult.Success;
                resp.SessionId = this._sessionId;
                resp.Value = new System.Collections.Generic.Dictionary<String, Object>();
                return resp;
            }
            if (driverCommandToExecute == "sendKeysToElement")
            {
                object[] array = (object[])parameters["value"];

                string stringfinal = (string)array[0].ToString();


                parameters.Add("text", stringfinal);

            }
            if (driverCommandToExecute == "executeScript")
            {
                Console.WriteLine("");
            }
            var respBase = base.Execute(driverCommandToExecute, parameters);
            return respBase;
        }
    }
}

在其他 class 中,我使用了以下方法来正确使用 Selenium 等待。

   public Boolean WaitInteligente(WebDriverWait wait, string condition, By selector = null, 
            IWebElement optionalWebElement = null,string optionalstring = null,
            bool optionalbool = false,bool devolverexcepcion=true )
        {
            TimeSpan Tiempo = wait.Timeout;
            var globalclock = Stopwatch.StartNew();
            Boolean stop = false;
            double segundos = globalclock.Elapsed.TotalSeconds;
            Exception exception = null;
            //globalclock.Stop();
            while (segundos <= Tiempo.TotalSeconds)
            {
                Thread.Sleep(500);
                try
                {
                    segundos = globalclock.Elapsed.TotalSeconds;
                    if (condition == "ElementExists")
                        wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(selector));
                    if (condition == "ElementIsVisible")
                        wait.Until(ExpectedConditions.ElementIsVisible(selector));
                    if (condition == "ElementToBeClickable")
                        wait.Until(ExpectedConditions.ElementToBeClickable(selector));
                    if (condition == "ElementToBeSelected")
                        wait.Until(ExpectedConditions.ElementToBeSelected(selector));
                    if (condition == "FrameToBeAvailableAndSwitchToIt")
                        wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(selector));
                    if (condition == "InvisibilityOfElementLocated")
                        wait.Until(ExpectedConditions.InvisibilityOfElementLocated(selector));
                    if (condition == "PresenceOfAllElementsLocatedBy")
                        wait.Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(selector));
                    if (condition == "VisibilityOfAllElementsLocatedBy")
                        wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(selector));
                    if (condition == "AlertIsPresent")
                        wait.Until(ExpectedConditions.AlertIsPresent());
                    if (condition == "ElementToBeSelected")
                        wait.Until(ExpectedConditions.ElementToBeSelected(optionalWebElement));
                    if (condition == "InvisibilityOfElementWithText")
                        wait.Until(ExpectedConditions.InvisibilityOfElementWithText(selector,optionalstring));
                    if (condition == "StalenessOf")
                        wait.Until(ExpectedConditions.StalenessOf(optionalWebElement));
                    if (condition == "TextToBePresentInElement")
                        wait.Until(ExpectedConditions.TextToBePresentInElement(optionalWebElement,optionalstring));
                    if (condition == "TextToBePresentInElementLocated")
                        wait.Until(ExpectedConditions.TextToBePresentInElementLocated(selector, optionalstring));
                    if (condition == "TextToBePresentInElementValue")
                        wait.Until(ExpectedConditions.TextToBePresentInElementValue(selector, optionalstring));
                    if (condition == "TitleContains")
                        wait.Until(ExpectedConditions.TitleContains(optionalstring));
                    if (condition == "TitleIs")
                        wait.Until(ExpectedConditions.TitleIs(optionalstring));
                    if (condition == "UrlContains")
                        wait.Until(ExpectedConditions.UrlContains(optionalstring));
                    if (condition == "UrlMatches")
                        wait.Until(ExpectedConditions.UrlMatches(optionalstring));
                    if (condition == "UrlToBe")
                        wait.Until(ExpectedConditions.UrlToBe(optionalstring));
                    if (condition == "FrameToBeAvailableAndSwitchToIt")
                        wait.Until(ExpectedConditions.FrameToBeAvailableAndSwitchToIt(optionalstring));
                    if (condition == "AlertState")
                        wait.Until(ExpectedConditions.AlertState(optionalbool));
                    if (condition == "ElementSelectionStateToBe")
                        wait.Until(ExpectedConditions.ElementSelectionStateToBe(selector,optionalbool));
                    if (condition == "ElementSelectionStateToBe")
                        wait.Until(ExpectedConditions.ElementSelectionStateToBe(selector, optionalbool));


                    stop = true;
                    break;
                }
                catch (Exception e)
                {
                     e = new Exception(selector.ToString() + condition + e.Message);
                    exception = e;
                }
            }

            if (!stop && devolverexcepcion)
                throw exception;

            return stop;
        }

附加后无法正常工作的方法是 driver.FindElement(By.Id) 和 driver.FindElement(By.ClassName) 可以通过分别对 ID 或类名调用 By.CssSelector 来轻松规避。

我无法恢复的最重要的功能是使用

注入 js 脚本
  IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
var script = "your script";
js.ExecuteScript(script);

任何关于如何恢复注入脚本功能的想法都将不胜感激。