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作为驱动的声明类型。
- 编写驱动工厂类:
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; } } }
- 测试代码中调用工厂创建驱动:
// 通过配置文件、环境变量或命令行参数获取运行环境标识 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命令调用,避免类型依赖问题。
- 统一驱动创建逻辑:
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端的驱动配置逻辑封装为独立策略类,通过环境标识动态选择策略,实现代码解耦。
- 定义策略接口:
public interface IDriverConfigStrategy { IWebDriver Configure(string downloadPath, int maxWait); }
- 实现两端策略:
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; } }
- 动态选择策略创建驱动:
bool isMobile = bool.Parse(ConfigurationManager.AppSettings["IsMobile"]); IDriverConfigStrategy strategy = isMobile ? new MobileDriverStrategy() : new WebDriverStrategy(); IWebDriver _driver = strategy.Configure(_downloadPath, _maxWait);
内容的提问来源于stack exchange,提问作者Kev
相关产品推荐
相关产品推荐

