Electron 42.3.0 刚刚发布。这个版本最值得注意的变化是新增了 app.getApplicationInfoForProtocol()——一个让开发者能直接查询系统协议注册信息的 API。对于需要处理自定义 URL 协议(比如 myapp://)的桌面应用来说,这补上了长期以来的一块短板:以前你只能"注册",没法方便地"查回来"。
协议注册的老痛点
桌面应用经常需要注册自定义协议,让浏览器或其他应用通过 myapp://open?file=xxx 这样的链接唤起自己。Electron 早就提供了 app.setAsDefaultProtocolClient() 来完成注册,但问题在于:
- 注册之后,你不知道是否真的注册成功了
- 你无法查询某个协议当前绑定的是哪个应用
- 在多应用竞争同一协议时,缺乏判断当前状态的手段
开发者只能靠手动查注册表(Windows)或 lsregister dump(macOS)来确认,既麻烦又容易出错。
getApplicationInfoForProtocol() 做了什么
新 API 的用法非常直接——传入一个协议名,返回该协议当前默认处理应用的详细信息:
const { app } = require('electron')
// 查询 myapp:// 协议当前绑定的应用信息
app.getApplicationInfoForProtocol('myapp').then(info => {
console.log(info)
// 返回对象包含:name, path, iconPath 等字段
}).catch(err => {
console.error('查询失败:', err)
})
返回的 info 对象至少包含应用名称和可执行路径,让你能判断:
- 协议是否已被注册
- 注册的是不是你的应用
- 如果不是你的应用,是哪个竞品占了位
这在安装向导、首次启动检测、协议冲突提示等场景下非常实用。
实战:协议注册 + 状态检测的完整流程
下面是一个可运行的 Electron 最小示例,演示注册协议后立即查询验证:
// main.js — Electron 协议注册与检测最小示例
const { app, BrowserWindow } = require('electron')
const PROTOCOL = 'myapp'
let mainWindow
app.whenReady().then(async () => {
mainWindow = new BrowserWindow({
width: 600,
height: 400,
webPreferences: { nodeIntegration: true, contextIsolation: false }
})
// 1. 注册自定义协议
if (process.defaultApp) {
// 开发模式下需要带上进程路径
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [process.argv[1]])
} else {
app.setAsDefaultProtocolClient(PROTOCOL)
}
// 2. 查询协议绑定状态(新 API)
try {
const info = await app.getApplicationInfoForProtocol(PROTOCOL)
mainWindow.loadURL(
`data:text/html;charset=utf-8,${encodeURIComponent(`
<h2>协议注册检测结果</h2>
<pre>${JSON.stringify(info, null, 2)}</pre>
<p>协议 <strong>${PROTOCOL}://</strong> 已绑定到上述应用</p>
`)}`
)
} catch (e) {
mainWindow.loadURL(
`data:text/html;charset=utf-8,${encodeURIComponent(`
<h2>检测失败</h2>
<p>${e.message}</p>
`)}`
)
}
})
// 3. 处理从外部唤起的协议链接
app.on('open-url', (event, url) => {
event.preventDefault()
if (mainWindow) {
mainWindow.loadURL(
`data:text/html;charset=utf-8,${encodeURIComponent(`
<h2>收到协议唤起</h2>
<p>URL: ${url}</p>
`)}`
)
}
})
对应的 package.json:
{
"name": "protocol-demo",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^42.3.0"
}
}
运行方式:
# 安装依赖
npm install
# 启动应用
npm start
# macOS 上测试协议唤起(终端执行)
open "myapp://open?doc=hello"
# Windows 上测试协议唤起(PowerShell 执行)
Start-Process "myapp://open?doc=hello"
启动后会看到窗口显示当前协议绑定的应用信息。如果返回的 info.path 与你的应用路径一致,说明注册成功;否则说明协议被其他应用占用了。
安装与升级注意事项
升级到 42.3.0 本身很简单:
# 直接升级
npm install electron@42.3.0
# 或锁定版本
npm install electron@42.3.0 --save-exact
但有几个点值得留意:
- Chromium 与 Node 版本跟随:Electron 42 对应的 Chromium 和 Node.js 版本与 42.x 系列一致,如果你的代码依赖特定 Node API 版本,先核对 Electron 版本映射表。
- macOS 协议注册需要 Info.plist 配置:
setAsDefaultProtocolClient在 macOS 上只负责注册到系统,但应用打包时仍需在Info.plist中声明CFBundleURLTypes,否则 App Store 审核和某些系统版本下行为不一致。 - Windows 需要管理员权限:在某些 Windows 版本上,协议注册涉及 HKCR 注册表写入,可能触发 UAC 提示。安装包阶段处理比运行时处理更稳妥。
什么时候该用这个新 API
几个典型场景:
| 场景 | 用法 |
|---|---|
| 安装向导中提示协议冲突 | 查询后告知用户"该协议已被 AppX 占用,是否覆盖" |
| 首次启动时自检 | 确认协议确实绑定到了自己,而非被后续安装的其他应用抢走 |
| 多实例/多版本共存 | 判断当前协议指向的是哪个版本的可执行文件 |
| 卸载清理决策 | 查询确认后再决定是否调用 removeAsDefaultProtocolClient |
小结
getApplicationInfoForProtocol() 不是一个大而全的重构,但它精准地补上了协议注册流程中"查状态"这一步。以前这块只能靠平台特定的黑魔法,现在有了统一 API,跨平台逻辑可以写得更干净。
如果你正在维护一个依赖自定义协议唤起的 Electron 应用,升级到 42.3.0 后建议把协议状态检测加入首次启动流程——几行代码就能避免用户遇到"点了链接却唤起了别的应用"的困惑。