目录

DevTools 协议

本教程介绍如何将 Selenium、Playwright、Puppeteer 等自动化工具连接到嵌入在 .NET 应用程序中的浏览器。

Selenium、Playwright 和 Puppeteer 通常会启动各自的 Chrome 实例并对其进行控制。而使用 DotNetBrowser 时,浏览器已经存在:它运行在您的应用程序内部,并在 BrowserView 控件中显示网页。因此,这些工具无需启动浏览器,而是连接到已经存在的浏览器。

它们通过 Chrome DevTools Protocol(简称 CDP)进行连接——这与 Chrome DevTools 所使用的协议相同。DotNetBrowser 可以在本地 TCP 端口上公开远程调试端点,任何 CDP 客户端都可以连接到该端点。

连接后,这些工具会直接操作应用程序当前已经显示的页面。从测试代码发出的点击、导航和脚本执行操作都会反映在 BrowserView 控件中。这样,您就可以针对自己应用程序中的 Web UI 运行现有测试套件,而不是针对一个独立的浏览器进行测试。

打开端点 

创建 IEngine 实例时,在 EngineOptions.Builder 中设置 RemoteDebuggingPort:

C#
VB
IEngine engine = EngineFactory.Create(
    new EngineOptions.Builder
    {
        RemoteDebuggingPort = 9222
    }.Build()
);
Dim engine As IEngine = EngineFactory.Create(
    New EngineOptions.Builder() With {
        .RemoteDebuggingPort = 9222
    }.Build()
)

任何空闲的 TCP 端口都可以使用。本教程中,Selenium 使用 9222,Playwright 和 Puppeteer 使用 9223,MCP 服务器使用 9224。

可以使用 localhost 或 127.0.0.1 访问该端点。两者通常都能正常工作,但 localhost 有时可能会解析到一个端点并未监听的地址,从而导致连接被拒绝。

Engine 指南对该选项进行了更详细的说明。其中的 --remote-allow-origins 开关适用于客户端本身就是网页的情况,例如 DevTools 前端:浏览器会附加 Origin 请求头,如果该来源未被允许,Chromium 会返回 403。Selenium、Playwright 和 Puppeteer 不会发送 Origin 请求头,因此这些教程不需要使用该开关。

安全性 

远程调试端点不提供任何身份验证。只要同一台计算机上的某个进程能够访问该端口,它就可以控制该引擎中的页面。建议仅在本地开发和测试运行期间启用此功能,并在发布给用户的构建版本中保持禁用状态。

连接,而不是启动 

这些工具都提供两种模式:启动浏览器,或连接到正在运行的浏览器。使用 DotNetBrowser 时,您始终使用第二种模式,并操作已经打开的页面。

工具连接 API已打开的页面
SeleniumChromeOptions.DebuggerAddress驱动程序的当前页面
PlaywrightIBrowserType.ConnectOverCDPAsyncContexts[0].Pages[0]
Puppeteer使用 ConnectOptions.BrowserURL 调用 Puppeteer.ConnectAsyncPagesAsync() 中的第一项
MCP 服务器--cdp-endpoint(Playwright MCP)、--browser-url(Chrome DevTools MCP)当前标签页;list_pages 中的页面 1

BrowserView 显示的是初始化它时所使用的 IBrowser 实例,因此该页面正是用户看到的页面。DotNetBrowser 不支持由工具打开页面(例如 Playwright 和 Puppeteer 中的 NewPageAsync),因为浏览器是通过其他方式创建的:您的应用程序通过 IEngine.CreateBrowser 创建每个 IBrowser,而页面会打开弹出窗口处理程序所允许的弹出窗口。

这些教程均假定只有一个页面。如果引擎中有多个浏览器,或者已经打开了弹出窗口,则无法保证 Pages 和 PagesAsync() 的顺序——应根据页面 URL 进行匹配,而不是直接使用第一项。

匹配 Chromium 版本 

客户端需要与 Chromium 版本保持多大程度的一致,取决于所使用的工具。

ChromeDriver 直接按照 Chromium 版本进行版本控制,并且会拒绝连接到它无法识别的版本。DotNetBrowser 4.3.1 基于 Chromium 153.0.8010.37,因此 Selenium.WebDriver.ChromeDriver 包必须针对该 Chromium 版本构建。版本不匹配是 Selenium 连接失败最常见的原因。

Playwright 和 Puppeteer 可以容忍一定的版本差异。两者都有各自固定的 Chromium 版本,但在连接到其他版本时会使用协议中稳定的子集。因此,这些教程即使使用了针对早期 Chromium 版本构建的包,也仍然可以建立连接。不过,如果某项功能依赖较新的 CDP 命令,则该命令在客户端所使用的旧版协议中仍可能不存在。

在引擎运行后连接 

引擎启动后,端点便可接受连接。示例从窗口的 Load 处理程序中连接,或者在首次调用 Navigation.LoadUrl 后立即连接。虽然这样的执行顺序通常有效,但并没有任何保证。因此,连接失败时应进行重试,而不要将第一次失败视为致命错误。为了让代码专注于连接本身,示例仅记录连接失败的尝试。

CDP 调用是异步的,并且在 UI 线程之外运行。当结果需要传递到用户界面时,应按照所使用框架的要求将其封送回 UI 线程。窗口关闭时,请释放 IBrowser 和 IEngine 实例。

离屏渲染 

RemoteDebuggingPort 是引擎选项,不依赖于渲染模式。使用 RenderingMode.OffScreen 创建的引擎会以相同方式公开该端点,因此测试宿主可以控制页面,而无需在屏幕上显示窗口。代码完全相同;唯一的区别是没有可用于观察测试场景运行过程的 BrowserView。

各工具教程 

每篇教程介绍一种工具,包括需要引用的包、连接到引擎的代码,以及该工具特有的故障情形。

  • Selenium — 通过 ChromeDriver 连接 WebDriver 会话。
  • Playwright — 通过 CDP 连接 Playwright for .NET。
  • Puppeteer — 将 Puppeteer Sharp 连接到正在运行的引擎。
  • MCP servers — 让 AI 代理通过 Playwright MCP 或 Chrome DevTools MCP 操作页面。

完整项目均可在我们的代码仓库中获取: C#, VB.NET。