需求场景:突然收到产品一个需求,希望在已登陆的网页上能够唤起桌面端软件(Windows,exe)并且免登录跳转至指定路由位置,就像百度网盘那样,我将方案和完成示例的整个过程记录并整理成文档。
纯浏览器环境没有执行权限去打开软件,通过Electron、Node、浏览器插件可以打开软件,但不符合需求场景或成本略高。
所以选择通过请求URL Protocol
协议来达到目的,可以在安装客户端时将所需信息写入注册表,或者通过单独的注册表执行文件将信息写入注册表,在通过链接访问这个协议时,就会通过注册表找到相应的软件位置。
Windows Registry Editor Version 5.00
//HKEY_CLASSES_ROOT:注册表主目录,MyProjectName:协议名称
[ ]
@="URL:MyProjectName Protocol Handler"
"URL Protocol"=""
[ ]
@="G:\\Install\\Microsoft VS Code\\Code.exe %1"
[ ]
[ ]
[ ]
//指定exe的路径,本例子是 vscode
@="G:\\Install\\Microsoft VS Code\\Code.exe %1"
新建txt
文档,将以上代码输入,格式为Unicode
,保存并修改文件类型为reg
,双击执行,信任并将注册表成功导入。
导入成功后通过快捷键(win+R)输入regedit
打开注册表查看。
通过链接请求URL Protocol
协议,打开客户端。
<a href="MyProjectName://">启动客户端</a>
点击打开,则成功唤起客户端。
COMMUNICATION
因为需要在网页端登陆并唤起客户端,客户端免登陆过程并跳转到指定路径,所以需要双方通信,并将相关token信息和路由信息传递接收。
1、协议请求:通过协议请求地址携带参数
通过协议请求传递Token和位置信息,将参数拼接在协议地址之后,请注意敏感数据不要明文暴露。
<a href="MyProjectName://token=123&position=234" id='Btn'>启动客户端</a>
客户端工程师可通过该协议接收参数,数据格式为String,并包含协议名,可通过约定格式获取相关数据。
string _UserInfo = "MyProjectName://token=123&position=234"
优点:实现简单,代码量低,通信不容易被监听。
缺点:只能单向通信,需要客户端开启浏览器,通过路由地址携带参数的方式才能显示双向通信。
2、监听剪切板:通过剪贴板传递数据参数
双方约定数据格式,(如:MyProjectName://),监听到约定格式后开始获取相关数据,获取后清空剪切板,请注意敏感数据不要明文暴露。
const link = 'MyProjectName://'; // 私有协议
const token = '123';
const position = '234';
const url = `${link}token=${token}&position=${position}`; // 全参数
const clipboard = new ClipboardJS('#btn', {
text: (e) => url,//粘贴板返回url
});
$('#btn').click((e) => {
clipboard.destroy(); // 取消剪贴板绑定
clipboard.onClick(e); // 手动调用 onClick 事件触发剪贴板拷贝
});
clipboard.on('success', (e) => {
console.log('url:', e.text); // 成功回调 url: MyProjectName://token=123&position=234
});
优点:双方可以通过约定格式和反复监听板来实现双向数据传输。
缺点:需要频繁监听剪贴板数据,并且有一定数据泄露风险。
THINKING
问题:当URL Protocol
协议成功写入注册表后,用户未安装客户端,或者手动删除应用程序文件该如何处理呢?
需要判断当前环境是否安装了该应用程序:
单纯通过浏览器环境内是无法获得应用安装信息的,需要activex
、wscript.shell
等控件支持,并需要额外的授权确认。
上述方式开发成本高,有兼容问题,并带来不确定的合规风险。
经过对百度网盘的使用分析,它采用的更为简单的一种方式:
点击唤起:当在网页端点击下载按钮,发起URL Protocol
协议请求时。
发起轮询:会创建一个定时器,并开始轮询请求网页在定时器时间范围内(如10s)轮询获得服务端返回的唤起结果。
唤起成功:当客户端存在时,会唤起该软件,并传递参数,客户端将参数与服务端请求,轮询接口结果成功,表示已成功唤起。
建立连接:当唤起成功后,建立连接,数据通信,客户端进行指定行为操作。
唤起失败:在定时器范围内,轮询请求结果未成功连接,则表示唤起失败。
引导下载:唤起失败后,则引导用户重新下载客户端并安装,重新写入注册表,重试整个过程。
SUM UP
最后将上述过程整理并制作成流程图,成为一个解决网页唤起客户端的解决方案。