如何在前端调用电脑系统里的东西?
由于浏览器安全限制,前端是无法调用电脑里已安装的程序的(例如启动某个程序)。如何在用户知情同意的前提下来突破这个限制呢?
有一种办法:做一个桌面客户端,通过前端来进行调用。
方案一:本地Web Server
参见在Web开发中,如果无法回避ActiveX控件——一种让用户在非IE浏览器调用控件的思路。
按照这个方案,前端不仅可以调用Active X控件,还可以做其他事情——只要是Windows应用程序能做的,前端都能通过HTTP API来间接做到。
如果需要双向通信,可以对Windows程序做一些改进,将其变成WebSocket服务器、WebRTC服务器。
方案二:自定义协议
如果只需要单方面发指令,那么不必开发复杂的HTTP Server,注册一个自定义协议,然后前端就可以一键启动,像百度网盘、打开迅雷那样。Windows程序端只要对参数进行检查和处理即可。
协议配置
在Windows系统,通过修改注册表实现。假如协议为hello://
,那么需要进行以下配置:
HKEY_CLASSES_ROOT
hello
,在该层级中建立一个值,Url Protocol
,类型REG_SZ,内容为空shell
open
command
,默认值为启动指令,例如C:\xxx\xxx.exe --start "%1"
在C#配置自安装时可以这样写:
var key = Registry.ClassesRoot.OpenSubKey("hello", true);
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("hello");
}
key.SetValue("Url Protocol", "", RegistryValueKind.String);
var shell = key.CreateSubKey("shell");
var open = shell.CreateSubKey("open");
var command = open.CreateSubKey("command");
var path = Application.ExecutablePath;
command.SetValue("", "\"" + path + "\" --start \"%1\"", RegistryValueKind.String);
解析指令
当前端调用hello://aaa?bbb=ccc
时,程序收到的参数则是--start "hello://aaa?bbb=ccc"
,在Main函数则需要对前端传过来的命令行参数进行解析和处理。
以C#的System.CommandLine
库为例(需要安装NuGet程序包,并在安装之前勾选“包括预发行版”):
static async Task<int> Main(string[] args) {
// ......
var startOption = new Option<string>(
name: "--start",
description: "启动应用",
getDefaultValue: ()=>""
);
var rootCommand = new RootCommand("")
{
startOption
};
rootCommand.SetHandler((url) =>
{
// 在这里处理url,例如
if (url == "")
{
Application.Run(new MainForm());
}
else
{
var uri = new Uri(url);
var path = uri.GetLeftPart(UriPartial.Path).Replace(uri.Scheme + "://", "");
var query = HttpUtility.ParseQueryString(uri.Query);
// path为路径
// query为URL问号右面的参数,通过query.Get("xxx")获取
}
}, startOption);
return await rootCommand.InvokeAsync(args);
}
前端启动
直接设置一个链接hello://xxxxxx?xxxx=xxx
即可。
注意URL不能无限长。IE长度不能超过2083,Chrome不能超过8182,Firefox不超过65536。
如何检测是否安装了辅助程序
自定义协议没有回执,如果未启动成功,需要设法提醒用户安装客户端。如何判断自定义协议执行成功了呢?有一种办法是判断window是否失去了焦点,因为执行自定义协议会启动本机程序,会导致浏览器失去焦点,所以可以使用这种“黑科技”来判断。
有人已对启动和检测是否启动成功做了封装,详细代码参见ismailhabib/custom-protocol-detection
方案比较
方案 | 优点 | 缺点 |
---|---|---|
方案一:本地Web Server | 可进行复杂、双向交互 | 实现复杂,需专门处理HTTPS问题 |
方案二:自定义协议 | 实现简单,不需要考虑HTTPS | 前端只能单向发指令,没有回执,无法获取信息 |