You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ChromeDriver与RemoteWebDriver差异:.Net/C#项目合并分支遇驱动问题

合并.Net/C#/Selenium移动端与Web端分支的驱动统一配置方案

问题背景

我有一个基于.Net/C#/Selenium的项目,目前分为移动端和Web端两个分支,希望合并为单个分支,但驱动配置存在冲突:

  • 移动端使用RemoteWebDriver连接Appium服务,配置代码如下:
protected static RemoteWebDriver? _driver = null;

var options = new ChromeOptions();
options.PlatformName = "Android";
options.AddAdditionalChromeOption("androidPackage", "com.android.chrome");
options.AddArgument("PlatformName=Android");
options.AddArgument("platformVersion=6.0.0");
options.AddArgument("deviceName=Tab");
options.AddArgument("isRealMobile=true");
options.AddArgument("network=false");
Uri url = new Uri("http://127.0.0.1:4723/wd/hub");
_driver = new RemoteWebDriver(url, options);
  • Web端必须使用ChromeDriver才能正常调用ExecuteCdpCommand,否则会出现找不到该方法的错误,配置代码如下:
protected static ChromeDriver? _driver = null;

var options = new ChromeOptions();
options.AddArgument("enable-automation");
options.AddArgument("disable-dev-shm-usage");
options.AddArgument("ignore-certificate-errors");
options.AddArgument("ignore-ssl-errors");
options.AddArgument("disable-popup-blocking");
options.AddArgument("window-size=1920,1080");
if (!System.Diagnostics.Debugger.IsAttached)
{
    _isDebug = false;
    options.AddArgument("headless");
}
options.AddArgument("disable-gpu");
options.AddUserProfilePreference("download.default_directory", _downloadPath);
options.AddUserProfilePreference("profile.default_content_setting_values.automatic_downloads", 1);
options.AddUserProfilePreference("plugins.always_open_pdf_externally", true);
options.AddUserProfilePreference("download.prompt_for_download", false);
options.AddUserProfilePreference("download.directory_upgrade", true);

ChromeDriverService serviceObj = ChromeDriverService.CreateDefaultService();
_driver = new ChromeDriver(serviceObj, options, TimeSpan.FromSeconds(_maxWait));
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(_maxWait);
_driver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(_maxWait);
_driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(_maxWait);
_driver.Manage().Cookies.DeleteAllCookies();
_driver.Manage().Window.Maximize();
_driver.ExecuteCdpCommand(
    "Emulation.setTimezoneOverride",
    new Dictionary<string, object>
    {
        ["timezoneId"] = "Europe/London"
    });

解决方案

方法1:工厂模式统一驱动创建+类型判断兼容CDP命令

通过工厂类根据运行环境生成对应驱动,同时利用类型判断处理Web端专属的CDP命令,核心是统一使用IWebDriver作为驱动的声明类型。

  1. 编写驱动工厂类:
public static class DriverFactory
{
    public static IWebDriver CreateDriver(bool isMobile, string downloadPath, int maxWait)
    {
        if (isMobile)
        {
            // 移动端驱动配置逻辑
            var options = new ChromeOptions();
            options.PlatformName = "Android";
            options.AddAdditionalChromeOption("androidPackage", "com.android.chrome");
            options.AddArgument("PlatformName=Android");
            options.AddArgument("platformVersion=6.0.0");
            options.AddArgument("deviceName=Tab");
            options.AddArgument("isRealMobile=true");
            options.AddArgument("network=false");
            Uri url = new Uri("http://127.0.0.1:4723/wd/hub");
            return new RemoteWebDriver(url, options);
        }
        else
        {
            // Web端驱动配置逻辑
            var options = new ChromeOptions();
            options.AddArgument("enable-automation");
            options.AddArgument("disable-dev-shm-usage");
            options.AddArgument("ignore-certificate-errors");
            options.AddArgument("ignore-ssl-errors");
            options.AddArgument("disable-popup-blocking");
            options.AddArgument("window-size=1920,1080");
            if (!System.Diagnostics.Debugger.IsAttached)
            {
                options.AddArgument("headless");
            }
            options.AddArgument("disable-gpu");
            options.AddUserProfilePreference("download.default_directory", downloadPath);
            options.AddUserProfilePreference("profile.default_content_setting_values.automatic_downloads", 1);
            options.AddUserProfilePreference("plugins.always_open_pdf_externally", true);
            options.AddUserProfilePreference("download.prompt_for_download", false);
            options.AddUserProfilePreference("download.directory_upgrade", true);

            ChromeDriverService serviceObj = ChromeDriverService.CreateDefaultService();
            var driver = new ChromeDriver(serviceObj, options, TimeSpan.FromSeconds(maxWait));
            
            // 配置通用参数
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(maxWait);
            driver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(maxWait);
            driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(maxWait);
            driver.Manage().Cookies.DeleteAllCookies();
            driver.Manage().Window.Maximize();
            
            // 执行Web端专属CDP命令
            driver.ExecuteCdpCommand(
                "Emulation.setTimezoneOverride",
                new Dictionary<string, object> { ["timezoneId"] = "Europe/London" });
            
            return driver;
        }
    }
}
  1. 测试代码中调用工厂创建驱动:
// 通过配置文件、环境变量或命令行参数获取运行环境标识
bool isMobile = bool.Parse(ConfigurationManager.AppSettings["IsMobile"]);
IWebDriver _driver = DriverFactory.CreateDriver(isMobile, _downloadPath, _maxWait);

// 后续需要执行CDP命令时,先判断驱动类型
if (_driver is ChromeDriver chromeDriver)
{
    chromeDriver.ExecuteCdpCommand("your-cdp-command", new Dictionary<string, object>());
}

方法2:统一使用RemoteWebDriver,适配CDP命令调用

Web端也改用RemoteWebDriver连接本地ChromeDriver服务,利用Selenium 4+的IHasDevTools接口兼容CDP命令调用,避免类型依赖问题。

  1. 统一驱动创建逻辑:
public static IWebDriver CreateDriver(bool isMobile, string downloadPath, int maxWait)
{
    ChromeOptions options = new ChromeOptions();
    IWebDriver driver;

    if (isMobile)
    {
        // 移动端配置
        options.PlatformName = "Android";
        options.AddAdditionalChromeOption("androidPackage", "com.android.chrome");
        options.AddArgument("PlatformName=Android");
        options.AddArgument("platformVersion=6.0.0");
        options.AddArgument("deviceName=Tab");
        options.AddArgument("isRealMobile=true");
        options.AddArgument("network=false");
        driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4723/wd/hub"), options);
    }
    else
    {
        // Web端配置
        options.AddArgument("enable-automation");
        options.AddArgument("disable-dev-shm-usage");
        // ...其他Web端options配置
        
        // 连接本地ChromeDriver服务(默认端口9515)
        driver = new RemoteWebDriver(new Uri("http://localhost:9515"), options, TimeSpan.FromSeconds(maxWait));
        
        // 使用IHasDevTools接口执行CDP命令(Selenium 4+支持)
        if (driver is IHasDevTools devToolsDriver)
        {
            var devToolsSession = devToolsDriver.GetDevTools();
            devToolsSession.CreateSession();
            devToolsSession.SendCommand(
                DevToolsCommandEmulation.SetTimezoneOverride,
                new Dictionary<string, object> { ["timezoneId"] = "Europe/London" });
        }
        
        // 配置通用参数
        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(maxWait);
        driver.Manage().Cookies.DeleteAllCookies();
        driver.Manage().Window.Maximize();
    }
    
    return driver;
}

方法3:策略模式封装不同端配置

将移动端和Web端的驱动配置逻辑封装为独立策略类,通过环境标识动态选择策略,实现代码解耦。

  1. 定义策略接口:
public interface IDriverConfigStrategy
{
    IWebDriver Configure(string downloadPath, int maxWait);
}
  1. 实现两端策略:
public class MobileDriverStrategy : IDriverConfigStrategy
{
    public IWebDriver Configure(string downloadPath, int maxWait)
    {
        var options = new ChromeOptions();
        // 移动端配置逻辑
        Uri url = new Uri("http://127.0.0.1:4723/wd/hub");
        return new RemoteWebDriver(url, options);
    }
}

public class WebDriverStrategy : IDriverConfigStrategy
{
    public IWebDriver Configure(string downloadPath, int maxWait)
    {
        var options = new ChromeOptions();
        // Web端配置逻辑
        ChromeDriverService service = ChromeDriverService.CreateDefaultService();
        var driver = new ChromeDriver(service, options, TimeSpan.FromSeconds(maxWait));
        // 配置超时、CDP命令等
        return driver;
    }
}
  1. 动态选择策略创建驱动:
bool isMobile = bool.Parse(ConfigurationManager.AppSettings["IsMobile"]);
IDriverConfigStrategy strategy = isMobile ? new MobileDriverStrategy() : new WebDriverStrategy();
IWebDriver _driver = strategy.Configure(_downloadPath, _maxWait);

内容的提问来源于stack exchange,提问作者Kev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 13:05:08