你以为鸿蒙真机上跑 Electron 应用,拿 hdc fport 把端口映射到本地,再用 Playwright 连上去就能自动化?这条路走不通,不是工具不行,是鉴权围栏把它焊死了。

看完这篇,你拿到一套照抄就能用的真机调试三板斧。本文讲四件事:外部浏览器为什么进不去、主进程 inspector 怎么用、uitest 和 hilog 怎么配合、输入框到底怎么填。

一、先排雷:为什么外部浏览器驱动不了

你可能会想:宿主不是起了个 webserver 吗?我 hdc fport 把端口映射出来,再用 Playwright 连上去不就行了?

不行。 原因藏在 dsh 的 RPC 鉴权里:

  • 宿主的每个 RPC 方法都需要一个浏览器会话:GET / 只接受 ?token=<launchToken> 形式的启动令牌,校验通过后才下发一个与 authority 绑定的签名 cookie。
  • 缺 cookie,会在 RPC 分发之前就直接返回 401。
  • 而启动令牌从不落日志(dsh 的 web-runtime 以 printUrl: false 运行),渲染进程交换完令牌后还会重定向到干净的 /。

结果就是:外部浏览器(哪怕你经 hdc fport 把端口映射出来了)拿不到令牌、完不成鉴权。这条路,死。

所以真机调试得另起炉灶——我总结成「三板斧」,全是踩坑踩出来的。

二、板斧一:主进程 inspector(能力最强,首选)

既然外部进不去,那就从内部进去。

运行时启动 Electron 时默认带了 --inspect,主进程始终在 9229 端口暴露一个 Node inspector。这个上下文里 require 可用、能拿到 electron,既能查 dsh 宿主,也能驱动渲染进程。

三步走:

# ① 先建立无线调试连接(端口见设备 开发者选项 → 无线调试)
hdc tconn <设备IP>:<端口>

# ② 端口转发:本地 19229 → 设备 9229(本地用非默认端口避免冲突)
export MSYS_NO_PATHCONV=1   # Git Bash 否则会把 /data/... 重写成 Windows 路径
hdc fport tcp:19229 tcp:9229

# ③ 拿调试入口,记下 webSocketDebuggerUrl
curl -s http://127.0.0.1:19229/json/list

拿到 webSocketDebuggerUrl 后,用 Node 自带的全局 WebSocket(Node ≥ 22)走 CDP 求值。两条最常用的表达式:

// 有哪些窗口、各自在什么 URL
(async () => { const { BrowserWindow } = require('electron'); return JSON.stringify(BrowserWindow.getAllWindows().map(w => w.webContents.getURL())); })()

// 读取渲染进程可见文本
(async () => { const { BrowserWindow } = require('electron'); return await BrowserWindow.getAllWindows()[0].webContents.executeJavaScript('document.body.innerText'); })()

第一句确认「窗口加载到了正确的局域网 IP 端口」,第二句直接读页面文本做断言——比截图还省事。

三、板斧二:uitest(渲染进程 UI 自动化,仅点击)

如果只想做「点一下」级别的 UI 自动化,鸿蒙自带的 uitest 够用:

hdc shell uitest dumpLayout -p /data/local/tmp/layout.json
hdc file recv /data/local/tmp/layout.json ./layout.json   # 拿到每个节点的文本与坐标
hdc shell uitest uiInput click <x> <y>                     # 点击可以触达 Web 内容

但注意两个坑:

  • ⚠️ uitest uiInput text 和 uiInput keyEvent 无法触达 Web 内容(编辑器不是原生控件)——文本输入得靠板斧一的 Input.insertText(见第五节)。
  • ⚠️ dump 覆盖整屏,系统设置等其他窗口会一起出现。点击前先 aa start 把应用调到前台,再重新 dump 确认坐标。

四、板斧三:hilog + fport(确认宿主状态)

调试第一步永远是「宿主到底起来没、在哪个端口」。一句话:

hdc shell "hilog -x | grep dsh-harmony | tail -20"   # 找「host 就绪: http://<局域网IP>:<端口>/」

再经 hdc fport 探测 http://127.0.0.1:<端口>/,返回 401 就说明 webserver 可达、且鉴权围栏生效——宿主是活的。

五、最难的一下:Input.insertText 填输入框

这是我在真机自动化里卡最久的一下:输入框是 contenteditable 富文本编辑器(不是 <textarea>),而且受 React 受控——直接赋 value / innerText 不会被识别。

正确姿势是走 CDP 的 Input.insertText:

(async () => {
  const { BrowserWindow } = require('electron');
  const wc = BrowserWindow.getAllWindows()[0].webContents;
  const SEL = '[contenteditable="true"][role="textbox"]';
  await wc.executeJavaScript(`document.querySelector('${SEL}').focus()`);
  if (!wc.debugger.isAttached()) wc.debugger.attach('1.3');
  await wc.debugger.sendCommand('Input.insertText', { text: '…' });
  return await wc.executeJavaScript(`document.querySelector('${SEL}').innerText.length`);
})()

写完后,点 aria-label 为「发送消息」的按钮即可发出。

六、安全提示(务必看)

--inspect 是把双刃剑:任何拿到 hdc 的人,都能完全控制宿主进程(那个上下文里 require 可用)。

这个参数来自上游运行时的默认配置,不是本工程引入的。本地调试可以接受,但上架 AppGallery 前,必须评估在 release 构建里把它移除。

七、三板斧速查

板斧作用关键能力适用场景
主进程 inspectorCDP 求值,最强--inspect + hdc fport + WebSocket查状态、读文本、填输入框
uitest只点击dumpLayout + uiInput click简单点击级 UI 自动化
hilog + fport状态探测hilog -x + 端口探测确认宿主起来没、端口对不对

一句话记住:外部进不去,从主进程 inspector 进去;输入框别硬填,走 Input.insertText。

八、写在最后

以上就是鸿蒙真机调试的三板斧:主进程 inspector(CDP 求值,最强)→ uitest(点击自动化)→ hilog + fport(状态探测),外加两个关键认知——外部浏览器驱动不了(鉴权围栏),输入框要 Input.insertText。

如果你也在做鸿蒙 / Electron-on-鸿蒙的真机自动化,这套直接抄。

代码已开源:https://github.com/fellow99/dsh-desktop-hos,欢迎 star 支持。

下一篇我写适配踩坑 8 连:把 Electron 应用搬进鸿蒙,坑不在 Electron,在鸿蒙的沙箱和网络模型。关注并设为星标,别错过。

相关开源工程:

  • DeepSeek Harness(上游项目):https://github.com/deepseek-ai/deepseek-harness
  • dsh-market(插件市场):https://github.com/dsh-market/dsh-market
  • harmonypc-electron(Electron-on-鸿蒙运行时):https://atomgit.com/jianguoxu/harmonypc-electron
  • deepseek-harness-workspace(工作区总览):https://github.com/fellow99/deepseek-harness-workspace
  • dsh-desktop(桌面端):https://github.com/fellow99/dsh-desktop
  • dsh-desktop-hos(鸿蒙端):https://github.com/fellow99/dsh-desktop-hos

感谢各位关注,欢迎访问我的GitHub主页:https://fellow99.github.io/

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐