基于vue3+ts的前端网页,实现网页点击按钮打开本地exe运行文件的完整实例

核心原理

使用 URL Protocol 协议注册 + 前端跳转协议 的方式实现,兼容主流浏览器(需用户提前注册协议)。

完整实现步骤

1. 注册自定义 URL 协议(Windows 系统)

创建 open-app.reg 文件,内容如下:

复制代码
Windows Registry Editor Version 5.00

; 删除旧的(如果存在)
[-HKEY_CLASSES_ROOT\myapp]

[HKEY_CLASSES_ROOT\myapp]
@="URL:MyApp Protocol v2"
"URL Protocol"=""
"EditFlags"=dword:00000002  ; 强制重新关联

[HKEY_CLASSES_ROOT\myapp\DefaultIcon]
@="C:\\Path\\To\\YourApp.exe,0"

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

说明:

  • 替换 C:\Path\To\YourApp.exe 为实际 exe 路径(如 C:\ProgramFiles\MyApp\app.exe)
  • 双击运行该文件完成注册

2.Vue3 + TypeScript 前端实现

复制代码
<template>
  <button @click="openLocalApp" :disabled="isOpening">
    {{ isOpening ? '正在启动...' : '启动本地应用' }}
  </button>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      isOpening: false,
      fallbackShown: false
    };
  },
  methods: {
    async openLocalApp() {
      if (this.isOpening) return;
      
      this.isOpening = true;
      
      // 方法1:使用 iframe(最兼容)
      const hiddenFrame = document.createElement('iframe');
      hiddenFrame.style.display = 'none';
      hiddenFrame.src = 'myapp://launch?timestamp=' + Date.now(); // 添加时间戳避免缓存
      document.body.appendChild(hiddenFrame);
      
      // // 方法2:使用 window.open(备用)
      // const fallbackTimer = setTimeout(() => {
      //   if (!this.fallbackShown) {
      //     this.fallbackShown = true;
      //     window.open('myapp://launch', '_blank');
      //   }
      // }, 100);
      
      // 监听各种可能的事件来判断应用是否启动
      const cleanup = () => {
        this.isOpening = false;
        // clearTimeout(fallbackTimer);
        clearTimeout(failTimer);
        hiddenFrame.remove();
        window.removeEventListener('blur', blurHandler);
        document.removeEventListener('visibilitychange', visibilityHandler);
      };
      
      const blurHandler = () => {
        console.log('应用启动成功 - 窗口失去焦点');
        cleanup();
        
        // 可选:显示成功提示
        setTimeout(() => {
          alert('应用启动成功!');
        }, 100);
      };
      
      const visibilityHandler = () => {
        if (document.hidden) {
          console.log('应用启动成功 - 页面被隐藏');
          cleanup();
        }
      };
      
      window.addEventListener('blur', blurHandler, { once: true });
      document.addEventListener('visibilitychange', visibilityHandler, { once: true });
      
      // 超时处理
      const failTimer = setTimeout(() => {
        if (this.isOpening) {
          cleanup();
          
          // 提供详细的错误帮助
          const userChoice = confirm(
            '应用启动可能需要额外权限。\n\n' +
            '可能的原因:\n' +
            '1. 防火墙或安全软件阻止\n' +
            '2. 需要手动允许协议启动\n' +
            '3. 应用路径不正确\n\n' +
            '点击"确定"查看详细解决方案'
          );
          
          if (userChoice) {
            window.open('/help#protocol-guide', '_blank');
          }
        }
      }, 5000); // 5秒超时
    }
  }
});
</script>
相关推荐
Java后端的Ai之路4 小时前
06-React-Props
前端·react.js·前端框架
Flynt5 小时前
开源"间谍卫星"说数据全是真的,我把它的免key数据源挨个试了一遍
前端·开源·数据可视化
Csvn5 小时前
渲染管线
前端
程序员大阳5 小时前
副队长CSS教程(33)–圆角与透明
前端·css·透明·圆角
志尊宝5 小时前
Vue3 零基础每日笔记(082):文件上传实战——el-upload 校验、自定义上传、头像预览
前端·javascript·vue.js·笔记·#javascript·#vue.js
鬼手点金6 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
柳杉6 小时前
借助 Codex 和可视化工作流,从调研到完整实现,3D 大屏竟然可以这么简单
前端·ai编程·数据可视化
IMPYLH6 小时前
HTML 的 <wbr> 元素
前端·html
Dovis(誓平步青云)7 小时前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
IT_陈寒8 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端