Skip to content

CDP 专题 - Chrome DevTools Protocol 调用指南

📖 目录


概述

Chrome DevTools Protocol (CDP) 是 Chromium 浏览器提供的底层调试和控制协议。cWebView2Host 支持 VB6 直接调用 CDP,实现对浏览器行为的深度控制,远超 WebView2 公开 API 的能力范围。

✨ 核心特点

  • 🔧 同步/异步双模式 - 简单场景用同步调用获取结果,复杂场景用异步避免阻塞
  • 🍪 HttpOnly Cookie - 通过 CDP 获取 JavaScript 无法读取的 HttpOnly Cookie
  • 📸 截图捕获 - 调用 Page.captureScreenshot 实现页面截图
  • 🔍 DOM 深度操作 - 直接操控 DOM 树,不经过 JavaScript 层
  • 🌐 网络控制 - 拦截和修改网络请求/响应

同步调用

CallDevToolsProtocolMethodSync

阻塞当前线程直到 CDP 返回结果,最简单的使用方式:

vb
Public Function CallDevToolsProtocolMethodSync( _
    ByVal MethodName As String, _
    ByVal ParametersAsJson As String) As String

返回: CDP 响应的 JSON 字符串

内部机制: 使用 Sleep + DoEvents 循环等待,不影响 VB6 窗体消息循环。

示例:

vb
Dim wv As New cWebView2Host   ' 同步调用无需 WithEvents

Private Sub Form_Load()
    wv.Initialize Me.hWnd, "https://vb6.pro"
End Sub

Private Sub Command1_Click()
    ' 获取页面标题
    Dim title As String
    title = wv.CallDevToolsProtocolMethodSync( _
        "Runtime.evaluate", _
        "{""expression"":""document.title""}")
    MsgBox "Title: " & title
    
    ' 获取所有 Cookie
    Dim cookies As String
    cookies = wv.CallDevToolsProtocolMethodSync( _
        "Network.getCookies", _
        "{}")
    
    ' 获取浏览器版本
    Dim version As String
    version = wv.CallDevToolsProtocolMethodSync( _
        "Browser.getVersion", _
        "{}")
End Sub

何时使用同步模式

  • 简单的查询操作(获取属性、Cookie 等)
  • 需要立即获取结果继续后续逻辑
  • 不关心 UI 阻塞(或阻塞时间极短)

异步调用

CallDevToolsProtocolMethod

发起 CDP 调用后立即返回,结果通过事件异步回报:

vb
Public Sub CallDevToolsProtocolMethod( _
    ByVal MethodName As String, _
    ByVal ParametersAsJson As String, _
    ByVal CustomEventId As String)

参数:

  • CustomEventId - 自定义事件 ID,在 DevToolsProtocolResponse 事件中用于匹配响应

示例:

vb
Dim WithEvents wv As cWebView2Host   ' 异步需要 WithEvents

Private Sub Command1_Click()
    ' 发起多个异步 CDP 调用
    wv.CallDevToolsProtocolMethod "Page.captureScreenshot", "{}", "screenshot"
    wv.CallDevToolsProtocolMethod "DOM.getDocument", "{}", "domDoc"
    wv.CallDevToolsProtocolMethod "Runtime.evaluate", _
        "{""expression"":""document.URL""}", "pageUrl"
End Sub

Private Sub wv_DevToolsProtocolResponse(ByVal CustomEventId As Variant, ByVal JsonResponse As String)
    Select Case CustomEventId
        Case "screenshot"
            Debug.Print "Screenshot data received"
            ' JsonResponse 包含 base64 编码的截图数据
        
        Case "domDoc"
            Debug.Print "DOM document: " & Left(JsonResponse, 200)
        
        Case "pageUrl"
            Debug.Print "Page URL: " & JsonResponse
    End Select
End Sub

何时使用异步模式

  • 耗时操作(截图、大量 DOM 操作)
  • 需要同时发起多个 CDP 调用
  • 不希望阻塞 UI 线程

常用 CDP 方法

Runtime 域

方法参数用途
Runtime.evaluate{expression, returnByValue?, awaitPromise?}执行 JS 表达式
Runtime.callFunctionOn{functionDeclaration, objectId, arguments, returnByValue}在指定对象上调用函数
Runtime.getProperties{objectId, ownProperties}获取对象属性

Network 域

方法参数用途
Network.getCookies{urls?}获取 Cookie(含 HttpOnly)
Network.getAllCookies{}获取所有 Cookie
Network.deleteCookies{name, url?, domain?, path?}删除 Cookie
Network.setCookie{name, value, url?, domain?, path?, httpOnly?, secure?}设置 Cookie
Network.setExtraHTTPHeaders{headers}设置额外 HTTP 头

Page 域

方法参数用途
Page.captureScreenshot{format?, quality?, clip?}页面截图
Page.printToPDF{landscape?, paperWidth?, ...}打印为 PDF
Page.navigate{url, referrer?}导航
Page.reload{ignoreCache?}重新加载

DOM 域

方法参数用途
DOM.getDocument{depth?}获取文档根节点
DOM.querySelector{nodeId, selector}CSS 选择器查询
DOM.getOuterHTML{nodeId}获取元素 HTML
DOM.setAttributeValue{nodeId, name, value}设置属性值

Browser 域

方法参数用途
Browser.getVersion{}获取浏览器版本信息

简易模式 (cWebView2Cookies)

vb
' document.cookie 解析(不含 HttpOnly)
Dim simple As String
simple = wv.Cookies.GetCookies

' CDP Network.getCookies(含 HttpOnly,同步)
Dim full As String
full = wv.Cookies.GetCookiesFull
vb
' 获取所有 Cookie(含详细信息)
Dim cookies As String
cookies = wv.CallDevToolsProtocolMethodSync("Network.getAllCookies", "{}")
' 返回格式: {"result":{"cookies":[{name,value,domain,path,httpOnly,secure,...}]}}

' 设置 Cookie
wv.CallDevToolsProtocolMethodSync "Network.setCookie", _
    "{""name"":""token"",""value"":""abc123"",""domain"":"".example.com"",""httpOnly"":true}"

' 删除 Cookie
wv.CallDevToolsProtocolMethodSync "Network.deleteCookies", _
    "{""name"":""token"",""domain"":"".example.com""}"

性能与限制

同步调用超时

CallDevToolsProtocolMethodSync 默认超时为 5 秒。对于耗时的 CDP 操作(如截图),建议使用异步模式。

CDP 版本兼容

CDP 方法可用性取决于 WebView2 Runtime 版本。建议使用 Browser.getVersion 检查版本:

vb
Dim version As String
version = wv.CallDevToolsProtocolMethodSync("Browser.getVersion", "{}")
' 返回包含 product、protocolVersion 等字段

调用频率

CDP 调用比 JS 执行更重,应避免在循环中高频调用。对于批量操作,优先使用单次 JS 执行:

vb
' 避免:循环中大量 CDP 调用
For i = 0 To 100
    wv.CallDevToolsProtocolMethodSync "DOM.setAttributeValue", ...
Next

' 推荐:单次 JS 执行
wv.JsRun "document.querySelectorAll('.item').forEach(el => el.classList.add('active'))"

完整示例

页面截图

vb
Private Sub Command1_Click()
    wv.CallDevToolsProtocolMethod "Page.captureScreenshot", _
        "{""format"":""png""}", "screenshot"
End Sub

Private Sub wv_DevToolsProtocolResponse(ByVal CustomEventId As Variant, ByVal JsonResponse As String)
    If CustomEventId = "screenshot" Then
        ' JsonResponse 包含 base64 编码的 PNG 数据
        ' 解析并保存到文件...
        Debug.Print "Screenshot received, length: " & Len(JsonResponse)
    End If
End Sub

网络请求拦截

vb
' 设置额外请求头
wv.CallDevToolsProtocolMethodSync "Network.setExtraHTTPHeaders", _
    "{""headers"":{""X-Custom-Header"":""MyValue""}}"

修改 DOM 属性

vb
' 通过 CDP 修改元素属性
Dim result As String
result = wv.CallDevToolsProtocolMethodSync("Runtime.evaluate", _
    "{""expression"":""document.getElementById('title').textContent = 'New Title'""}")

最后更新: 2026-06-24

VB6及其LOGO版权为微软公司所有