基于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>
相关推荐
漏洞文库-Web安全1 小时前
CTFHub XSS通关:XSS-过滤关键词 - 教程
前端·安全·web安全·okhttp·网络安全·ctf·xss
chilavert3181 小时前
技术演进中的开发沉思-231 Ajax:页面内容修改
开发语言·前端·javascript
一只小bit1 小时前
Qt 信号与槽:信号产生与处理之间的重要函数
前端·c++·qt·cpp·页面
nono牛1 小时前
30天Shell脚本编程实战(14天逆袭)
前端·chrome·bash
晚霞的不甘1 小时前
实战深研:构建高可靠、低延迟的 Flutter + OpenHarmony 智慧教育互动平台(支持离线教学、多端协同与国产化适配)
前端·javascript·flutter
董世昌411 小时前
前端跨域问题:原理、8 种解决方案与实战避坑指南
开发语言·前端·javascript
吃炸鸡的前端1 小时前
Vite创建react项目
前端·react.js·前端框架
IT_陈寒1 小时前
Redis性能提升40%!我用这5个冷门但高效的配置优化了千万级QPS应用
前端·人工智能·后端
GISer_Jing1 小时前
SSE Conf 大会分享——AI Native 3D开发革命,让创意不再被技术门槛阻挡(推荐!!!)
前端·人工智能·3d·信息可视化