【问题记录】— web页面调用本地程序
起因:
最近由于项目需要在web页面中调用本地部署的exe程序;进而对该功能实现做了对应了解;以及存在的问题进行记录。
要实现该功能就不得不说浏览器自定义协议;解决办法:那么它是什么呢?
浏览器自定义协议:
浏览器自定义协议,其实是微软提供 Asynchronous Pluggable Protocols;可以用来注册本地应用程序到 URI Scheme
https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)
实现自定义协议方式—添加注册表:
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\协议名称]
@="程序运行地址"
"URL Protocol"="" [HKEY_CLASSES_ROOT\calldemo\DefaultIcon]
@="程序运行地址,1" [HKEY_CLASSES_ROOT\calldemo\shell] [HKEY_CLASSES_ROOT\calldemo\shell\open] [HKEY_CLASSES_ROOT\calldemo\shell\open\command]
@="程序地址" \"%1\""
自定义协议实现示例:
示例实现:实现一个本地Exe,并注册到注册表中;并运行效果。(程序比较简单,可以查看github)
程序实现写入注册表主要逻辑:
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
RegisterUrlProtocol(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var from = new Form1();
//显示输入参数
from.Args = args;
Application.Run(from);
}
/// <summary>
/// 注册自定义协议
/// </summary>
private static void RegisterUrlProtocol()
{
try
{
//检查是否注册自定义协议:如未注册则注册
Register register = new Register("calldemo", RegDomain.ClassesRoot);
if (!register.IsSubKeyExist("calldemo"))
{
//注册:
register.CreateSubKey();
register.WriteRegeditKey("", $"{Application.ExecutablePath}");
register.WriteRegeditKey("URL Protocol", "");
if (!register.IsSubKeyExist(@"calldemo\DefaultIcon"))
{
register.CreateSubKey(@"calldemo\DefaultIcon");
register.SubKey = @"calldemo\DefaultIcon";
register.WriteRegeditKey("", $"{Application.ExecutablePath},1");
}
if (!register.IsSubKeyExist(@"calldemo\shell"))
{
register.CreateSubKey(@"calldemo\shell");
register.CreateSubKey(@"calldemo\shell\open");
register.CreateSubKey(@"calldemo\shell\open\command");
register.SubKey = @"calldemo\shell\open\command";
//添加默认键
register.WriteRegeditKey("", $"\"{Application.ExecutablePath}\" \"%1\"");
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
throw;
}
}
创建检验html:
<a href="calldemo:123qwe">UrlProtocolDemo</a>
运行效果:

github地址:https://github.com/cwsheng/URLProtocolDemo.git
问题记录:
1、关于js中检验浏览器自定义协议是否存在,现在没有教好的解决办法?
开源项目:https://github.com/ismailhabib/custom-protocol-detection(亲测无效,且不维护了)
https://github.com/Veryfirefly/custom-protocol-detection(原理同上,也无效)
问题:https://stackoverflow.com/questions/836777/how-to-detect-browsers-protocol-handlers
2、每次调用启动exe,都会新运行一个程序实例;可以通过程序实现判断该程序是否已经在运行。
#region 确保程序只运行一个实例
private static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
//遍历与当前进程名称相同的进程列表
foreach (Process process in processes)
{
//如果实例已经存在则忽略当前进程
if (process.Id != current.Id)
{
//保证要打开的进程同已经存在的进程来自同一文件路径
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
{
//返回已经存在的进程
return process;
}
}
}
return null;
}
//3.已经有了就把它激活,并将其窗口放置最前端
private static void HandleRunningInstance(Process instance)
{
ShowWindowAsync(instance.MainWindowHandle, 1); //调用api函数,正常显示窗口
SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(System.IntPtr hWnd);
#endregion
最后:
当然该方式不一定是唯一实现方式,也可以尝试使用WebAssembly实现本地运行程序逻辑,本次未进行验证
如果js判断自定义协议是否存在,有好到方法也希望能得到大家的解答。
【问题记录】— web页面调用本地程序的更多相关文章
- 从web页面启动winform程序的实现方法
本文实现的需求是: A.通过web页面启动winform程序: B.将页面的参数传递给winform程序: C.winform程序已经启动并正在运行时,从web页面不能重新启动winform程序,只是 ...
- 通过私有协议Chrome浏览器页面打开本地程序
近期方有这样的要求:这两个系统,根据一组Chrome开展,根据一组IE开展,需要Chrome添加一个链接,然后进入IE该系统的开发.这,需要Chrome跳转到创建一个链接IE浏览器指定的页面.同时也实 ...
- 细说Web页面与本地电脑通讯
话说在很久很久以前.Web页面与客户的本地电脑Localhost通讯,有两种方式: 1.Flash 2.ActiveX控件 由于Flash本人不是很了解,也给出不了什么示例代码, 对于ActiveX控 ...
- 网页调用本地程序(Windows下浏览器全兼容)
用网页调用本地应用程序的思路是,先进行注册表注册自定义一个URL Protocol协议,再利用URL Protocol实现网页调用本地应用程序. 1.先写一个注册表文件,将其保存为.reg后缀的注册表 ...
- web页面调用支付宝支付
web页面调用支付宝支付 此文章是前端单独模拟完成支付,若在线上环境则需要后台配合产生签名等参数 在蚂蚁金服开放平台申请沙箱环境 将沙箱环境中的密钥.应用网关.回调地址补全,生成密钥的方法在此 配置好 ...
- [转]从网页Web上调用本地应用程序(.jar、.exe)的主流处理方法
这个方法主要思路是利用自定义URL Protocol来调用应用程序.浏览器在解析到自定义URL Protocol之后,会寻找注册表,然后通过注册表启动相应的程序,然后启动改程序,传入参数.对于我这个项 ...
- web页面和小程序页面实现瀑布流效果
小程序实现瀑布流效果,和web页面差不多,都要经过以下步骤: 1).加载图片,获取图片的宽高度: 2).根据页面需要显示几列计算每列的宽度: 3).根据图片真实宽度和每列的宽度比,计算出图片需要显示的 ...
- js调用本地程序
前几天,做项目时候用到js调用本地的程序,找了好多资料,一种是写入注册表,一种是写一个浏览器插件,相对来说,写一个注册表更简单一点,因为需求很紧.下面就是我的总结,希望可以对你们有所帮助,具体从哪里找 ...
- 自定义浏览器协议,实现web程序调用本地程序
转自 http://blog.csdn.net/talking12391239/article/details/40712759 亲测可用 tencent://Message/?Uin=000000 ...
随机推荐
- 如何将Docker升级到最新版本
很早以前,已经使用过了Docker了,但是没有使用过 Docker 部署 NetCore 3.1 的应用程序,今天部署的时候发生了一些问题,解决办法:Docker 版本太低了,那就升级一下.下面是具体 ...
- Java学习的第五十五天
1.例11.1继承学生类 import java.util.Scanner; import java.util.*; public class Cjava { public static void m ...
- 编排yml文件剖析
# yaml格式的pod定义文件完整内容: apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,Pod metadata: #必选, ...
- Vmware - 安装并启动 Centos 7
下载 Linux 安装包 http://mirrors.aliyun.com/centos/7.8.2003/isos/x86_64/ 不同版本的 Centos https://mirrors.ali ...
- JDK 8 新增的 LongAdder,得过来看一下
前言 在介绍 AtomicInteger 时,已经说明在高并发下大量线程去竞争更新同一个原子变量时,因为只有一个线程能够更新成功,其他的线程在竞争失败后,只能一直循环,不断的进行 CAS 尝试,从而浪 ...
- spring 中aop 切面实战
切面相关注解: @Aspect : 声明该类为一个注解类 @Pointcut : 定义一个切点 @Before : 在切点之前执行 @After : 在切点之后执行 不管目标方法是否执行成功 @Aft ...
- Skip Lists: A Probabilistic Alternative to Balanced Trees 阅读笔记
论文地址:https://15721.courses.cs.cmu.edu/spring2018/papers/08-oltpindexes1/pugh-skiplists-cacm1990.pdf ...
- Spider--补充--selenium的使用
# Selenium (firefox) # 1,介绍: # selenium 是一个 web 的自动化测试工具,是一个包,可以支持 C. java.ruby.python.或都是 C# 语言. # ...
- Java—多线程
一.多线程 原理: 一个cpu内核有"一个指针",由于cpu的频率过高,所以感觉不到卡顿.(伪线程) 二.进程&线程 进程:进程指正在运行的程序.确切的来说,当一个程序进入 ...
- python之 《zip,lambda, map》
1.zip 对于zip我们一般都是用在矩阵上 eg: a = [1,2,3] b = ['a', 'b', 'c'] x = zip(a, b) print(x) print(list(x)) 结果是 ...