zoukankan      html  css  js  c++  java
  • 【问题记录】— 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_ROOTcalldemoDefaultIcon]
    @="程序运行地址,1"
    
    [HKEY_CLASSES_ROOTcalldemoshell]
    
    [HKEY_CLASSES_ROOTcalldemoshellopen]
    
    [HKEY_CLASSES_ROOTcalldemoshellopencommand]
    @="程序地址" "%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(@"calldemoDefaultIcon")) { register.CreateSubKey(@"calldemoDefaultIcon"); register.SubKey = @"calldemoDefaultIcon"; register.WriteRegeditKey("", $"{Application.ExecutablePath},1"); } if (!register.IsSubKeyExist(@"calldemoshell")) { register.CreateSubKey(@"calldemoshell"); register.CreateSubKey(@"calldemoshellopen"); register.CreateSubKey(@"calldemoshellopencommand"); register.SubKey = @"calldemoshellopencommand"; //添加默认键 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判断自定义协议是否存在,有好到方法也希望能得到大家的解答。

  • 相关阅读:
    关于TFS中WorkItem的探究
    Pro Android4 面试题归纳
    truncate 、delete、drop
    获取数据库中所有表的行数及其他信息
    【转】高手速成android开源项目【View篇】
    Can't create handler inside thread that has not called Looper.prepare()解决办法
    Android使用获取HTML
    .net操作EXCEL
    ASP.NET发送邮件
    如何使用 MasterPage
  • 原文地址:https://www.cnblogs.com/cwsheng/p/14056848.html
Copyright © 2011-2022 走看看