自定义协议URL protocal 在网页端打开本地应用程序

参考链接:
https://blog.csdn.net/u010271602/article/details/82144072
https://blog.csdn.net/cainiaokan/article/details/44103361
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/123427259

在web中调起本地exe,同时需要在调起失败时提醒安装
URL protocal:自定义协议 需要在window的注册列表中注册 测试时可以用txt复制以下代码,另存为.reg文件。双击后点确定

Windows Registry Editor Version 5.00  // 必须有这句

[HKEY_CLASSES_ROOT\flyinsono]  // 这里所有的的flyinsono就是自定义的协议名,可以自行修改
@="URL:flyinsono Protocol Handler"   //自定义提示
"URL Protocol"=""

[HKEY_CLASSES_ROOT\flyinsono\DefaultIcon]
@="G:\\Cheat Engine 7.0\\Cheat Engine.exe" // exe的地址

[HKEY_CLASSES_ROOT\flyinsono\shell]

[HKEY_CLASSES_ROOT\flyinsono\shell\open]

[HKEY_CLASSES_ROOT\flyinsono\shell\open\command]
@="\"G:\\Cheat Engine 7.0\\Cheat Engine.exe\" \"%1\"" // 也是exe的地址,但是要注意(")号和(\) 
                                                      // 后面的%1是必要的 有问题可以试试%L 意思是接收参数

页面上使用以下函数:

// 全局参数: isDone(防止重复点击)、protocolTimeout(计时器,用于超时判断)

// 文中的所有this为VUE中需要。原生环境下要删除

// onclick函数
handleInitiate() {
  this.$message.warning('正在调起杏聆荟')

  const _this = this 
  const account = 'connie'
  const s = '192.168.6.6'
  const href = `flyinsono://?a=${account}&s=${s}`
  // 创建一个button的input,用以检测是否成功调用
  const assistEl = document.createElement('input')
  assistEl.id = 'flyinsonoBtn'
  assistEl.type = 'button'
  // 设置样式防止干扰页面布局 不能使用display: none
  assistEl.style.opacity = '0'
  assistEl.style.position = 'fixed'
  assistEl.onclick = () => {
    // 实际触发逻辑在这里
    _this.launchApplication(href).then(() => {
      this.$message.success('杏聆荟已启动')
    }).catch(() => {
      this.$message.error('未安装杏聆荟,请在安装后刷新浏览器')
    })
  }

  document.body.append(assistEl)

  // 必须把焦点给刚刚创建的button型input,不然检测不了
  assistEl.focus()
  // 手动触发点击事件
  assistEl.click()
},

// 调用exe
launchApplication(url) {
  const _this = this
  return new Promise((resolve, reject) => {
    // 获取刚刚创建的button型input
    const assistEl = document.getElementById('flyinsonoBtn')
    // 创建iframe用于调用自定义协议
    const triggerEl = document.createElement('iframe')
    triggerEl.style.display = 'none'

    // 防止重复点击
    if (!_this.isDone) return
    _this.isDone = false

    assistEl.focus()
    assistEl.onblur = function() {
      // 此处以button型input失去焦点作为检测办法
      // 因为调用成功的时候,改元素会立刻失去焦点
      if (document.activeElement && document.activeElement !== assistEl) {
        // 防止误触导致检测失效
        assistEl.focus()
      } else {
        // 调用成功
        done()
        resolve()
      }
    }

    triggerEl.onerror = function() {
      done()
      // 进入错误事件回调函数说明没有注册协议
      reject()
    }

    try {
      triggerEl.src = url
      // 开始调用exe
      document.body.append(triggerEl)
    } catch (e) {
      done()
      // 捕获到异常说明没有注册协议
      reject()
    }

    this.protocolTimeout = setTimeout(function() {
      done()
      // 如果超过一定时间仍然没有变化,说明没有注册协议
      reject()
    }, 1800)

    function done() {
      // 不管成功失败,调用结束后立即还原现场
      _this.isDone = true
      assistEl.onblur = null
      triggerEl.onerror = null
      clearTimeout(_this.protocolTimeout)

      triggerEl.remove()
      assistEl.remove()
    }
  })
}
posted @   九月旅人  阅读(17)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示