Web 网页如何唤起本地 Windows 应用并传递参数(含 Electron 自动注册 + 手动配置指南)

Web 网页如何唤起本地 Windows 应用并传递参数(含 Electron 自动注册 + 手动配置指南)

本文基博客 《点击页面按钮唤醒桌面的应用 windows》 扩展整理

在现代企业级系统中,Web 应用常常需要与本地桌面程序协作。例如:

  • 点击网页上的"打印"按钮,自动调用专用打印软件;
  • 在 OA 系统中点击"打开合同",直接唤起 PDF 阅读器或电子签章工具;
  • 第三方 SaaS 平台集成客户已有的 Windows 软件,实现数据互通。

你有没有注意到:飞书、钉钉、百度网盘、腾讯会议等软件,都能通过网页一键唤起本地客户端?

✅ 比如:

  • 飞书:lark://open/message?...
  • 钉钉:dingtalk://action=call&user=xxx
  • 百度网盘:baidunetdisk://download?file=...

这些能力背后,依赖的是 Windows 的 自定义 URL 协议(Custom URL Scheme) 机制。

Windows 的 自定义 URL 协议(Custom URL Scheme) 是一种系统级机制,允许开发者注册一个以 xxx:// 开头的协议(如 myapp://),并将其关联到本地某个可执行程序。

当用户在浏览器、资源管理器或其他支持 URL 调用的地方点击或访问该协议链接时,Windows 会自动启动对应的应用程序,并将完整的 URL 作为命令行参数传递给它。

本文将从零开始,教你如何:

  1. 手动注册自定义协议(适合测试或非 Electron 场景);
  2. 让 Electron 应用在安装时自动注册协议(开箱即用);
  3. 网页如何安全传参,本地程序如何接收;
  4. 解答一个关键问题:应用在后台运行和完全未启动,行为有何不同?

一、真实案例:主流软件如何做到"网页唤起本地应用"?

当你在浏览器点击飞书会议链接 lark://meet/12345,系统会立即启动飞书客户端并加入会议。这是因为在你首次安装飞书时,它就悄悄做了以下事情:

  • 在 Windows 注册表中注册了 lark 协议;
  • 将该协议绑定到 Feishu.exe 的安装路径;
  • 声明:"今后所有 lark:// 开头的请求,请交给我处理"。

类似地:

软件 协议示例 用途
钉钉 dingtalk:// 发消息、拨号、打开工作台
百度网盘 baidunetdisk:// 下载文件、打开本地目录
腾讯会议 zoommtg:// / wemeet:// 加入会议
微信(Windows) weixin:// 打开聊天(部分版本支持)

💡 这些软件无需用户手动配置,安装即生效------这正是我们要实现的目标。


二、方案选择:手动注册 vs 自动注册

方式 适用场景 是否需要用户操作
手动修改注册表 测试、内部工具、非打包应用 ✅ 需要
Electron 安装自动注册 正式产品、分发给客户 ❌ 无需

下面分别介绍两种方式。


三、方式一:手动配置注册表(详细步骤)

📌 适用于:C++/C#/Python 打包的 exe、临时测试、无安装包的场景

步骤 1:确定你的应用路径

假设你的程序位于:
C:\MyApp\MyApp.exe

步骤 2:打开注册表编辑器

  • Win + R,输入 regedit,回车。

步骤 3:创建协议项

  1. 导航到 HKEY_CLASSES_ROOT
  2. 右键 → 新建 → 项,命名为你的协议名(如 myapp
  3. myapp 项内:
    • 右键 → 新建 → 字符串值 ,名称为 URL Protocol(值留空)
    • 双击左侧 (默认),设置值为 "URL: MyApp Protocol"(可选描述)

步骤 4:绑定到应用程序

继续在 myapp 下创建层级:

复制代码
myapp
└── shell
    └── open
        └── command

进入 command,双击 (默认),输入:

text 复制代码
"C:\MyApp\MyApp.exe" "%1"

⚠️ 注意:

  • 路径必须用英文双引号包裹;
  • %1 表示完整的 URL(如 myapp://action?file=xxx

步骤 5:验证是否成功

  • Win + R,输入 myapp://test
  • 如果你的程序启动,说明注册成功!

替代方法:使用 .reg 文件一键导入

新建 register_myapp.reg,内容如下:

reg 复制代码
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\myapp]
@="URL: MyApp Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\myapp\shell\open\command]
@="\"C:\\MyApp\\MyApp.exe\" \"%1\""

双击运行即可写入注册表。


四、方式二:Electron 应用安装时自动注册协议(推荐)

使用 electron-builder 打包时,只需简单配置,安装程序会自动完成注册。

步骤 1:在 package.json 中声明协议

json 复制代码
{
  "name": "myapp",
  "build": {
    "appId": "com.example.myapp",
    "productName": "MyApp",
    "win": {
      "target": "nsis"
    },
    "protocols": [
      {
        "name": "MyApp Protocol",
        "schemes": ["myapp"]
      }
    ]
  }
}

步骤 2:主进程监听协议唤起

js 复制代码
// main.js
const { app } = require('electron');

app.on('open-url', (event, url) => {
  event.preventDefault();
  handleProtocol(url);
});

// Windows 启动时从 argv 获取
if (process.defaultApp) {
  const url = process.argv.find(arg => arg.startsWith('myapp://'));
  if (url) handleProtocol(url);
}

function handleProtocol(fullUrl) {
  console.log('收到:', fullUrl);
  // 解析参数并处理业务逻辑
}

步骤 3:构建安装包

bash 复制代码
npx electron-builder --win

生成的 Setup.exe 在安装时会自动注册 myapp:// 协议,用户无需任何操作。


五、Web 页面如何唤起应用?(Vue2 示例)

vue 复制代码
<template>
  <button @click="launchApp">打开本地应用</button>
</template>

<script>
export default {
  methods: {
    launchApp() {
      const params = new URLSearchParams({
        action: 'print',
        filePath: 'C:\\Reports\\Q4.pdf'
      });
      const url = `myapp://handle?${params.toString()}`;
      // myapp://handle?action=print&filePath=C%3A%5CReports%5CQ4.pdf
      window.location.href = url;
    }
  }
}
</script>

🔔 浏览器可能会弹出安全提示:"是否允许打开 MyApp?"------这是正常现象。


六、关键问题:应用在后台运行 vs 完全未启动,有区别吗?

有!而且行为完全不同。

场景 系统行为 Electron 如何处理
应用未启动 Windows 会启动新进程,并将 URL 作为命令行参数传入(process.argv[1] app.whenReady() 中解析 argv
应用已在后台运行 Windows 会向已有进程 发送 WM_COPYDATA 或触发 second-instance 事件 监听 app.on('second-instance', ...)

Electron 推荐写法(兼容两种情况):

js 复制代码
const gotTheLock = app.requestSingleInstanceLock();

if (!gotTheLock) {
  app.quit();
} else {
  app.on('second-instance', (event, argv) => {
    const url = argv.find(a => a.startsWith('myapp://'));
    if (url) handleProtocol(url);
  });

  app.whenReady().then(() => {
    createWindow();
    // 首次启动检查
    const url = process.argv.find(a => a.startsWith('myapp://'));
    if (url) handleProtocol(url);
  });
}

✅ 这样无论应用是否已运行,都能正确接收参数。


七、重要提醒:Web 无法知道本地应用是否已安装或运行!

这是一个常见误区:

❌ "网页能否检测用户是否安装了 MyApp?"

答案:不能。

出于安全限制,浏览器无法探测本地文件系统或进程列表。你只能:

  • 尝试唤起协议;
  • 如果失败(如弹出"找不到应用"错误),引导用户去下载安装;
  • 或通过其他间接方式(如本地 HTTP 服务、WebSocket 心跳)判断,但这需要额外开发。

因此,良好的用户体验应包含 fallback 机制

js 复制代码
function launchApp() {
  const url = 'myapp://test';
  window.location.href = url;
  
  // 3 秒后若未跳转,说明可能未安装
  setTimeout(() => {
    if (!document.hidden) {
      alert('未检测到 MyApp,请先安装');
      window.open('https://example.com/download');
    }
  }, 3000);
}

八、总结

能力 实现方式
✅ 网页唤起本地应用 自定义 URL 协议(myapp://
✅ 安装时自动注册 electron-builder + protocols 配置
✅ 手动注册(测试用) 修改 HKEY_CLASSES_ROOT\myapp
✅ 传参与接收 URL 查询参数 + Electron argv / open-url
✅ 兼容后台/未启动 使用 requestSingleInstanceLock + second-instance
❌ 检测是否安装 浏览器无法实现,需 fallback 引导

通过本文方法,你可以像飞书、钉钉一样,打造"网页一键唤起本地应用"的无缝体验。

🎯 适用场景:政企系统集成、医疗设备控制、金融终端、离线任务调度等。

现在,轮到你的应用登场了!🚀

相关推荐
IT_陈寒2 小时前
Redis 性能优化实战:5个被低估的配置项让我节省了40%内存成本
前端·人工智能·后端
chilavert3182 小时前
技术演进中的开发沉思-261 Ajax:动画优化
前端·javascript·ajax
尘心cx2 小时前
前端-APIs-day3
开发语言·前端·javascript
武藤一雄2 小时前
一款基于WPF开发的BEJSON转换工具
windows·c#·json·wpf
烂不烂问厨房2 小时前
前端自适应布局之等比例缩放
开发语言·前端·javascript
kong79069282 小时前
环境搭建-运行前端工程
前端
CodeLinghu3 小时前
提示词链模式:一种利用LLM大语言模型处理复杂任务的强大范式
前端·人工智能·语言模型
J2虾虾3 小时前
关于Ant Design Vue
前端·javascript·vue.js
程序员笨鸟3 小时前
[特殊字符] React 高频 useEffect 导致页面崩溃的真实案例:从根因排查到彻底优化
前端·javascript·学习·react.js·面试·前端框架