相关文章推荐
面冷心慈的熊猫  ·  请问,用 Electron ...·  1 月前    · 
傲视众生的鞭炮  ·  electron调用DLL开发记录 | ...·  1 月前    · 
独立的荔枝  ·  electron ...·  2 天前    · 
性感的香槟  ·  Electron中常用对话框-打开文件对话框 ...·  2 天前    · 
千年单身的手套  ·  浏览器或electron程序打开视频或者内容 ...·  2 天前    · 
坐怀不乱的椰子  ·  菏泽拟新建一处涉铁立交,规划方案公布!_腾讯新闻·  1 年前    · 
高大的小虾米  ·  党员干部当以“严”涵养好作风_红星网_中共湖 ...·  2 年前    · 
打篮球的长颈鹿  ·  政府信息公开目录·  2 年前    · 
伤情的感冒药  ·  女校攻略 - 🌈️包子漫畫·  2 年前    · 
留胡子的黑框眼镜  ·  【文章】哪吒E申报信息曝光 ...·  2 年前    · 
Code  ›  Electron通过协议url唤起应用开发者社区
软件 url const electron
https://cloud.tencent.com/developer/article/1781419
苦恼的打火机
2 年前
码客说
0 篇文章

Electron通过协议url唤起应用

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
码客说
社区首页 > 专栏 > 码客 > Electron通过协议url唤起应用

Electron通过协议url唤起应用

作者头像
码客说
发布 于 2021-01-29 07:19:29
2.8K 0
发布 于 2021-01-29 07:19:29
举报

前言

对于一个 URL 来说,其实就是指定了一个协议( protocol ),然后让系统用对应的应用去打开它。如 myapp://openapp?name=1&pwd=2 ,系统会去找到已经注册了 myapp 这个协议的应用,然后把 URL 当做参数传过去。

这样我们就可以在浏览器中通过一个 <a> 标签简单地唤起应用了。

<a href="myapp://openapp?name=1&pwd=2">打开应用</a>

单实例运行

首先,每次打开一个协议 URL,系统都会启动一个新的应用。这就需要应用自己去判断,把 URL 当做参数传给已有的应用,还是自己直接处理。

Electron 提供了一个简单的方法,来获取一个锁,只有第一个调用的实例才能获取成功,后面的其他实例则把参数传过去,然后退出就可以了。

const { app } = require('electron');
// 获取单实例锁
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
  // 如果获取失败,说明已经有实例在运行了,直接退出
  app.quit();
}

注册协议

我们期望通过协议来启动应用,所以要先注册一个协议到系统中,调用 API 即可:

const PROTOCOL = 'myapp';
const args = [];
if (!app.isPackaged) {
  // 如果是开发阶段,需要把我们的脚本的绝对路径加入参数中
  args.push(path.resolve(process.argv[1]));
// 加一个 `--` 以确保后面的参数不被 Electron 处理
args.push('--');
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args);

这里的 args 是预定义的参数,对 macOS 没有作用,但是在 Windows 上却是必不可少的。

在 Windows 上启动一个协议URL时,实际上是用如下参数启动了我们的应用:

${process.execPath} ${...args} myapp://...

需要注意的是,在开发阶段,我们是通过 electron . 或者 electron path/to/script.js 来启动的应用,所以 process.argv[1] 是我们的脚本路径,传给系统时,这个参数也不能少,否则启动的就是一个纯粹的 Electron 壳,而不是我们的应用了。这时,这个参数就要通过这里的 args 一起注册到系统中了。

根据 这个帖子 ,我们可以在预定义的参数最后加一个 -- ,来阻止其他参数直接被 Electron 处理。

获取参数

第二个实例运行的时候,自己就退出了,那么第一个实例如何能获取到启动第二个实例的参数呢?这里 macOS 和 Windows 上的行为是不一致的,需要分别处理。

// 如果打开协议时,没有其他实例,则当前实例当做主实例,处理参数
handleArgv(process.argv);
// 其他实例启动时,主实例会通过 second-instance 事件接收其他实例的启动参数 `argv`
app.on('second-instance', (event, argv) => {
  // Windows 下通过协议URL启动时,URL会作为参数,所以需要在这个事件里处理
  if (process.platform === 'win32') {
    handleArgv(argv);
// macOS 下通过协议URL启动时,主实例会通过 open-url 事件接收这个 URL
app.on('open-url', (event, urlStr) => {
  handleUrl(urlStr);
});

Windows 下 argv 的处理有一个需要注意的地方,就是开发阶段要跳过前两个参数( execPath 和当前启动脚本):

function handleArgv(argv) {
  const prefix = `${PROTOCOL}:`;
  // 开发阶段,跳过前两个参数(`electron.exe .`)
  // 打包后,跳过第一个参数(`myapp.exe`)
  const offset = app.isPackaged ? 1 : 2;
  const url = argv.find((arg, i) => i >= offset && arg.startsWith(prefix));
  if (url) handleUrl(url);
}

完整的协议链接跟HTTP链接类似,如下:

myapp://openapp?name=1&pwd=2

但大部分情况下,我们可能只需要最后的 key-value 参数就可以了,所以可以省略成:

myapp://?name=1&pwd=2

链接可以通过全局对象 URL 来解析:

function handleUrl(urlStr) {
  // myapp://?name=1&pwd=2
  const urlObj = new URL(urlStr);
  const { searchParams } = urlObj;
  console.log(urlObj.search); // -> ?name=1&pwd=2
  console.log(searchParams.get('name')); // -> 1
  console.log(searchParams.get('pwd')); // -> 2
  // 根据需要做其他事情
}

完整代码如下:

const path = require('path');
const { app } = require('electron');
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
  app.quit();
const PROTOCOL = 'myapp';
const args = [];
if (!app.isPackaged) {
  args.push(path.resolve(process.argv[1]));
args.push('--');
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args);
handleArgv(process.argv);
app.on('second-instance', (event, argv) => {
  if (process.platform === 'win32') {
    // Windows
    handleArgv(argv);
// macOS
app.on('open-url', (event, urlStr) => {
  handleUrl(urlStr);
function handleArgv(argv) {
  const prefix = `${PROTOCOL}:`;
  const offset = app.isPackaged ? 1 : 2;
  const url = argv.find((arg, i) => i >= offset && arg.startsWith(prefix));
  if (url) handleUrl(url);
function handleUrl(urlStr) {
  // myapp://?name=1&pwd=2
  const urlObj = new URL(urlStr);
  const { searchParams } = urlObj;
  console.log(urlObj.search); // -> ?name=1&pwd=2
  console.log(searchParams.get('name')); // -> 1
  console.log(searchParams.get('pwd')); // -> 2
}

收到协议打开页面

let autologindata = null;
function handleUrl(urlStr) {
    const urlObj = new URL(urlStr);
    const {searchParams} = urlObj;
    let userid = searchParams.get('userid');
    let sectionid = searchParams.get("sectionid");
    console.log(userid); // -> 1
    console.log(sectionid); // -> 2
    autologindata = {
        "userid": userid,
        "sectionid": sectionid
    console.info(autologindata);
}

首页面设置

const isDevelopment = !app.isPackaged;
function createWindow() {
    loginWindow = new BrowserWindow({
        width: 750,
        height: 472,
        frame: false,
        show: false,
        transparent: true,
        resizable: false,
        webPreferences: {
            nodeIntegration: true,
            enableRemoteModule: true,
            webSecurity: false,
            contextIsolation: false,
    if (isDevelopment) {
        loginWindow.loadURL(`file://${__dirname}/login.html`)
    } else {
        loginWindow.loadURL(format({
            pathname: path.join(__dirname, 'login.html'),
            protocol: 'file',
            slashes: true
    loginWindow.once("ready-to-show", () => {
        loginWindow.show();
        if (autologindata) {
            loginWindow.webContents.send("autologin", autologindata);
 
推荐文章
面冷心慈的熊猫  ·  请问,用 Electron 打印标签有什么推荐库或者Nodejs相关工具之类的么
1 月前
傲视众生的鞭炮  ·  electron调用DLL开发记录 | 生子当如哈士奇的小空间
1 月前
独立的荔枝  ·  electron 打开选择文件框_electron打开文件选择框
2 天前
性感的香槟  ·  Electron中常用对话框-打开文件对话框、保存文件对话框、提示对话框 - 霸道流氓
2 天前
千年单身的手套  ·  浏览器或electron程序打开视频或者内容比较多的网站会导致电脑卡顿 - Microsoft Q&A
2 天前
坐怀不乱的椰子  ·  菏泽拟新建一处涉铁立交,规划方案公布!_腾讯新闻
1 年前
高大的小虾米  ·  党员干部当以“严”涵养好作风_红星网_中共湖南省委组织部
2 年前
打篮球的长颈鹿  ·  政府信息公开目录
2 年前
伤情的感冒药  ·  女校攻略 - 🌈️包子漫畫
2 年前
留胡子的黑框眼镜  ·  【文章】哪吒E申报信息曝光 定位双门轿跑/造型用力有点猛_车家号_汽车之家
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号