起因:

 最近由于项目需要在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页面调用本地程序的更多相关文章

  1. 从web页面启动winform程序的实现方法

    本文实现的需求是: A.通过web页面启动winform程序: B.将页面的参数传递给winform程序: C.winform程序已经启动并正在运行时,从web页面不能重新启动winform程序,只是 ...

  2. 通过私有协议Chrome浏览器页面打开本地程序

    近期方有这样的要求:这两个系统,根据一组Chrome开展,根据一组IE开展,需要Chrome添加一个链接,然后进入IE该系统的开发.这,需要Chrome跳转到创建一个链接IE浏览器指定的页面.同时也实 ...

  3. 细说Web页面与本地电脑通讯

    话说在很久很久以前.Web页面与客户的本地电脑Localhost通讯,有两种方式: 1.Flash 2.ActiveX控件 由于Flash本人不是很了解,也给出不了什么示例代码, 对于ActiveX控 ...

  4. 网页调用本地程序(Windows下浏览器全兼容)

    用网页调用本地应用程序的思路是,先进行注册表注册自定义一个URL Protocol协议,再利用URL Protocol实现网页调用本地应用程序. 1.先写一个注册表文件,将其保存为.reg后缀的注册表 ...

  5. web页面调用支付宝支付

    web页面调用支付宝支付 此文章是前端单独模拟完成支付,若在线上环境则需要后台配合产生签名等参数 在蚂蚁金服开放平台申请沙箱环境 将沙箱环境中的密钥.应用网关.回调地址补全,生成密钥的方法在此 配置好 ...

  6. [转]从网页Web上调用本地应用程序(.jar、.exe)的主流处理方法

    这个方法主要思路是利用自定义URL Protocol来调用应用程序.浏览器在解析到自定义URL Protocol之后,会寻找注册表,然后通过注册表启动相应的程序,然后启动改程序,传入参数.对于我这个项 ...

  7. web页面和小程序页面实现瀑布流效果

    小程序实现瀑布流效果,和web页面差不多,都要经过以下步骤: 1).加载图片,获取图片的宽高度: 2).根据页面需要显示几列计算每列的宽度: 3).根据图片真实宽度和每列的宽度比,计算出图片需要显示的 ...

  8. js调用本地程序

    前几天,做项目时候用到js调用本地的程序,找了好多资料,一种是写入注册表,一种是写一个浏览器插件,相对来说,写一个注册表更简单一点,因为需求很紧.下面就是我的总结,希望可以对你们有所帮助,具体从哪里找 ...

  9. 自定义浏览器协议,实现web程序调用本地程序

    转自  http://blog.csdn.net/talking12391239/article/details/40712759 亲测可用 tencent://Message/?Uin=000000 ...

随机推荐

  1. 如何将Docker升级到最新版本

    很早以前,已经使用过了Docker了,但是没有使用过 Docker 部署 NetCore 3.1 的应用程序,今天部署的时候发生了一些问题,解决办法:Docker 版本太低了,那就升级一下.下面是具体 ...

  2. Java学习的第五十五天

    1.例11.1继承学生类 import java.util.Scanner; import java.util.*; public class Cjava { public static void m ...

  3. 编排yml文件剖析

    # yaml格式的pod定义文件完整内容: apiVersion: v1       #必选,版本号,例如v1 kind: Pod       #必选,Pod metadata:       #必选, ...

  4. Vmware - 安装并启动 Centos 7

    下载 Linux 安装包 http://mirrors.aliyun.com/centos/7.8.2003/isos/x86_64/ 不同版本的 Centos https://mirrors.ali ...

  5. JDK 8 新增的 LongAdder,得过来看一下

    前言 在介绍 AtomicInteger 时,已经说明在高并发下大量线程去竞争更新同一个原子变量时,因为只有一个线程能够更新成功,其他的线程在竞争失败后,只能一直循环,不断的进行 CAS 尝试,从而浪 ...

  6. spring 中aop 切面实战

    切面相关注解: @Aspect : 声明该类为一个注解类 @Pointcut : 定义一个切点 @Before : 在切点之前执行 @After : 在切点之后执行 不管目标方法是否执行成功 @Aft ...

  7. Skip Lists: A Probabilistic Alternative to Balanced Trees 阅读笔记

    论文地址:https://15721.courses.cs.cmu.edu/spring2018/papers/08-oltpindexes1/pugh-skiplists-cacm1990.pdf ...

  8. Spider--补充--selenium的使用

    # Selenium (firefox) # 1,介绍: # selenium 是一个 web 的自动化测试工具,是一个包,可以支持 C. java.ruby.python.或都是 C# 语言. # ...

  9. Java—多线程

    一.多线程 原理: 一个cpu内核有"一个指针",由于cpu的频率过高,所以感觉不到卡顿.(伪线程) 二.进程&线程 进程:进程指正在运行的程序.确切的来说,当一个程序进入 ...

  10. 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)) 结果是 ...