Skip to content

Web前端如何启动本地可执行文件

如果在用户本地电脑上有个exe可执行文件,不能修改这个可执行文件本身,想在浏览器中通过点击按钮,调用这个exe文件,Web前端可以做到么?

由于浏览器的安全限制,是不允许直接调用exe文件的。但是有时候非要实现这种需求,因此只能用一些折中的方法。

  • 方法1 注册表协议法
    方法通用且简单,但是经过测试只有FireFox浏览器支持,Chrome浏览器禁用这个请求。
  • 方法2 本地监听法
    自己写一个小的服务端在本地一直监听请求。
  • 方法3 IE有自己的调用方法

下面对每个方法分别进行介绍。

方法1 注册表协议法

这个方法的步骤是:

  1. 新建一个注册表文件,里面描述一个新协议,这个协议的动作是:当访问这个协议时,打开一个可执行文件。
  2. 前端点击时,访问这个协议的链接,就会调用可执行文件。

比如我们需要打开的文件位置在:e:/abc/needOpen/needOpen.exe。做新设立一个协议叫做newopenprotocol,则编写注册表文件如下:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\newopenprotocol]
@="URL:newopenprotocol Protocol"
"URL Protocol"=""

[HKEY_CLASSES_ROOT\newopenprotocol\DefaultIcon]
@="cmd.exe,1"

[HKEY_CLASSES_ROOT\newopenprotocol\shell]

[HKEY_CLASSES_ROOT\newopenprotocol\shell\open]

[HKEY_CLASSES_ROOT\newopenprotocol\shell\open\command]
@="cmd /k e: && cd e:/abc/needOpen && needOpen.exe"

保存这个注册表文件,后缀名是.reg。点击执行这个文件,协议就被写入注册表了。

然后前端访问这个协议链接,各种方式都可以:

js
// HTML
<a href="newopenprotocol://test">点击执行exe</a>
// js
window.open("newopenprotocol://test");

甚至在浏览器直接访问这个链接也行。

经测试,火狐浏览器打开时会有浏览器的提示框。

注意:

  1. 协议后面的test目前并没有什么用处。这个方法由于谷歌浏览器不能使用,因此我也没有继续研究下去。有兴趣的同学可以研究一下协议后面的文字是否可以作为参数传递给可执行文件。
  2. 让用户自己编辑注册表文件写入可执行文件路径有点不现实。可以写一个windows脚本文件与可执行文件在同一路径,一起分发给用户。windows脚本动态生成注册表文件,并且自动写入注册表。详细在后面介绍。

这个方法来源于网络博客:谷歌浏览器chrome调用cmd命令。虽然文章名字包含:“谷歌浏览器chrome”,但是经过我实际测试,只有火狐浏览器支持这个功能。可能是谷歌浏览器的旧版本支持,但是新版本限制了。

方法2 本地监听法

可以自己开发一个小的可执行程序,监听前端发的web请求。收到请求后,我们自己编写的可执行程序启动本地的可执行文件即可。想要启动本地可执行文件的关键就是本地有一个小服务端,我们通过本地网络与服务端通信,服务端负责启动可执行文件。这种方法对于任何浏览器都兼容,但是需要用户额外安装程序。这个程序需要常驻电脑后台。

不过,前端请求localhost本地依然会发生跨域。但这时候可以用一些常见的方式来规避跨域请求,相对更容易。如果这种需求较大,可以做一个通用的工具。我这边正好有这种其他人开发的类似工具(非开源),因此可以直接使用。

当然,如果这个可执行文件可以适配开发,直接让可执行文件本身提供服务端功能即可。

方法3 IE有自己的调用方法

IE浏览器下有自己的调用程序的方法,但是IE浏览器已经逐渐被淘汰,因此本文不涉及相关内容,感兴趣可以上网自行搜索。

用Windows脚本自动生成并注册表文件并写入

上面我们提到,由于可执行程序安装的位置不同,因此注册表也不同。但是让用户自己编辑注册表肯定不现实,容易出错又不安全。因此我们可以写一个windows脚本,自动生成注册表文件并写入。假设我们需要写的注册表文件类似这样:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\XXXX\YYYY]
"needOpen"="E:\\abc\\needOpen\\needOpen.exe"

注意注册表文件的路径必须用两个反斜杠。同样后缀名是.reg,点击可执行。在系统搜索“注册表编辑器”,输入路径(这个路径是我瞎编的)

HKEY_CURRENT_USER\Software\XXXX\YYYY

可以检查是否正确写入注册表。注册表编辑器可以手动添加/删除注册表,调试脚本的时候会用到。

windows脚本文件后缀名是.bat。脚本文件如下:

bat
@echo off
echo Windows Registry Editor Version 5.00> regi.reg
:: echo=是输出空行
echo=>> regi.reg
echo [HKEY_CURRENT_USER\Software\XXXX\YYYY]>> regi.reg
:: 双引号符号需要用^转义
set a=^"needOpen^"=^"
:: 注册表写入路径需要两个反斜杠号\\
set c=\\needOpen.exe^"
:: chdir是获取当前路径,结果保存在变量b中
for /F %%i in ('chdir') do (set b=%%i)
:: 替换变量b中的单个反斜杠为两个反斜杠
set bb=%b:\=\\%
:: 三个字符串在同一行输出
echo %a%%bb%%c% >> regi.reg
echo=>> regi.reg
:: 执行注册表文件
regi.reg

:: 代表这一行是注释。我写的注释基本上说的很清楚了。这个脚本需要与可执行文件在同一路径,压缩后一起分发给用户。用户收到后,解压缩到合适的位置,执行这个脚本文件,可能需要管理员权限。

浏览器行为的思考

为什么前端启动可执行文件这么困难?因为这有较高的安全风险。我们的前端代码本身是运行在浏览器中的,收到浏览器制约,不能直接影响电脑环境本身。但本地可执行文件的权限是非常大的,是如果前端代码可以随便启用电脑上的可执行文件,那么就可以直接操控电脑了。如果是恶意的前端代码,可以给用户电脑造成严重的破坏。因此,浏览器会倾向于限制前端启动可执行文件的能力。希望前端代码仅限制在浏览器中活动。即使目前采用的方法,也有被限制的风险。在高版本的谷歌浏览器中,即使请求本地的图片也会有跨域限制。

因此随着后续浏览器安全功能的完善,前端想要启动本地可执行文件,可能会越来越难的。 ​