代码之家  ›  专栏  ›  技术社区  ›  Chris Craft

如何检测浏览器的协议处理程序?

  •  74
  • Chris Craft  · 技术社区  · 15 年前

    我已经创建了一个自定义的URL协议处理程序。

    http://

    mailto://

    custom://

    我已经注册了一个WinForms应用程序来进行相应的响应。这一切都很好。

    但是我希望能够优雅地处理用户还没有安装自定义URL协议处理程序的情况。

    为了能够做到这一点,我需要能够检测浏览器的注册协议处理程序,我假设从JavaScript。但我一直找不到一个方法来调查这些信息。我希望能找到解决这个问题的办法。

    15 回复  |  直到 15 年前
        1
  •  35
  •   scunliffe    15 年前

    这将是一个 非常 非常 黑的

    • 将链接正常放入。。。
    • 但是附加一个onclick处理程序给它,它设置了一个计时器并为窗口添加了一个onblur处理程序
    • (理论上)如果浏览器处理链接(应用程序X)将从窗口加载窃取焦点。。。
    • 如果onblur事件触发,请清除计时器。。。
    • 否则在3-5秒内让你的超时触发。。。并通知用户“嗯,看起来你没有安装超级酷应用程序。。。您想现在安装吗?(确定)(取消)

        2
  •  18
  •   EricLaw    10 年前

    没有什么好的跨浏览器方法可以做到这一点。在Win8+上的IE10+中,一个新的 msLaunchUri api允许您启动协议,如下所示:

    navigator.msLaunchUri('skype:123456', 
      function() 
      { 
        alert('success');
      }, 
      function()
      {
        alert('failed');
      } 
    ); 
    

    我在这里进一步讨论这个话题: http://blogs.msdn.com/b/ieinternals/archive/2011/07/14/url-protocols-application-protocols-and-asynchronous-pluggable-protocols-oh-my.aspx

        3
  •  16
  •   Hugh Guiney    13 年前

    Custom scheme and content handlers (据我所知,Firefox是 implementor 但不幸的是,目前还没有办法检查处理程序是否已经存在 proposed ,但没有随访。这似乎是有效使用自定义处理程序的一个关键特性,作为开发人员,我们应该注意这个问题,以便实现它。

        4
  •  13
  •   jtomson    15 年前

    似乎没有直接的方法通过javascript来检测是否存在注册了协议处理程序的已安装应用程序。

    在iTunes模式中,苹果向其服务器提供URL,然后服务器提供运行一些javascript的页面:

    http://ax.itunes.apple.com/detection/itmsCheck.js

    因此,iTunes安装程序显然为主要浏览器部署了插件,然后可以检测到这些浏览器的存在。

    如果你的插件已经安装,那么你可以合理地确定重定向到你的应用程序特定的url将会成功。

        5
  •  11
  •   Natim    15 年前

    每个示例使用Javascript确认对话框:

    You need this software to be able to read this link. Did you install it ?
    
    if yes: create a cookie to not ask next time; return false and the link applies
    if false: window.location.href = '/downloadpage/'
    
        6
  •  5
  •   quano    12 年前

    如果您控制了要运行的程序(代码),查看用户是否成功运行应用程序的一种方法是:

    1. 在尝试打开自定义协议之前,向服务器脚本发出AJAX请求,该脚本将用户的意图保存在数据库中(例如,保存userid和他想要做的事情)。

    2. 然后,打开程序。

    3. 让程序请求服务器删除数据库条目(使用intent数据找到正确的行)。

    4. 让javascript轮询服务器一段时间,看看数据库条目是否消失了。如果条目消失,您将知道用户成功地打开了应用程序,否则条目将保留(您可以稍后使用cronjob将其删除)。

    我没有试过这个方法,只是想了想。

        7
  •  4
  •   Community CDub    7 年前

    我终于得到了一个跨浏览器(chrome32,firefox27,ie11,safari6)的解决方案,它结合了 this 还有一个超级简单的狩猎扩展。这个解决方案中的很多都在这个和这个中以这样或那样的方式被提及 other question .

    剧本如下:

    function launchCustomProtocol(elem, url, callback) {
        var iframe, myWindow, success = false;
    
        if (Browser.name === "Internet Explorer") {
            myWindow = window.open('', '', 'width=0,height=0');
            myWindow.document.write("<iframe src='" + url + "'></iframe>");
    
            setTimeout(function () {
                try {
                    myWindow.location.href;
                    success = true;
                } catch (ex) {
                    console.log(ex);
                }
    
                if (success) {
                    myWindow.setTimeout('window.close()', 100);
                } else {
                    myWindow.close();
                }
    
                callback(success);
            }, 100);
        } else if (Browser.name === "Firefox") {
            try {
                iframe = $("<iframe />");
                iframe.css({"display": "none"});
                iframe.appendTo("body");
                iframe[0].contentWindow.location.href = url;
    
                success = true;
            } catch (ex) {
                success = false;
            }
    
            iframe.remove();
    
            callback(success);
        } else if (Browser.name === "Chrome") {
            elem.css({"outline": 0});
            elem.attr("tabindex", "1");
            elem.focus();
    
            elem.blur(function () {
                success = true;
                callback(true);  // true
            });
    
            location.href = url;
    
            setTimeout(function () {
                elem.off('blur');
                elem.removeAttr("tabindex");
    
                if (!success) {
                    callback(false);  // false
                }
            }, 1000);
        } else if (Browser.name === "Safari") {
            if (myappinstalledflag) {
                location.href = url;
                success = true;
            } else {
                success = false;
            }
    
            callback(success);
        }
    }
    

    myinject.js文件:

    window.postMessage("myappinstalled", window.location.origin);
    

    window.addEventListener('message', function (msg) {
        if (msg.data === "myappinstalled") {
            myappinstalledflag = true;
        }
    }, false);
    

    这假设与自定义协议关联的应用程序将管理Safari扩展的安装。

    在所有情况下,如果回调返回false,您知道要通知用户应用程序(即,它的自定义协议)没有安装。

        8
  •  3
  •   Brian    15 年前

    你说你需要检测浏览器的协议处理程序-真的吗?

    如果您做了一些类似于从sourceforge下载文件时发生的事情呢?假设你想打开我的应用程序://什么的。与其简单地创建指向它的链接,不如创建指向另一个通过HTTP访问的HTML页面的链接。然后,在该页面上,假设您正试图为他们打开应用程序。如果不起作用,他们需要安装你的应用程序,他们可以通过点击你提供的链接来完成。如果真的成功了,那你就准备好了。

        9
  •  3
  •   Ken Geis grunk    9 年前

    您可以尝试以下方法:

    function OpenCustomLink(link) {
    
        var w = window.open(link, 'xyz', 'status=0,toolbar=0,menubar=0,height=0,width=0,top=-10,left=-10');
        if(w == null) {            
            //Work Fine
        }
        else {
            w.close();
            if (confirm('You Need a Custom Program. Do you want to install?')) {
                window.location = 'SetupCustomProtocol.exe'; //URL for installer
            }
        }
    }
    
        10
  •  1
  •   user200565    15 年前

    我正在尝试做一些类似的事情,我刚刚发现了一个适用于Firefox的技巧。如果你把它和IE的技巧结合起来,你就可以有一个在两个主要浏览器上都能工作的(我不确定它在Safari中是否工作,我知道它在Chrome中不工作)

    if (navigator.appName=="Microsoft Internet Explorer" && document.getElementById("testprotocollink").protocolLong=="Unknown Protocol") {
        alert("No handler registered");
    } else {
        try {
            window.location = "custom://stuff";
        } catch(err) {
            if (err.toString().search("NS_ERROR_UNKNOWN_PROTOCOL") != -1) {
                alert("No handler registered");
            }
        }
    }
    

    为了让它工作,你还需要在页面的某个地方有一个隐藏的链接,比如:

    <a id="testprotocollink" href="custom://testprotocol" style="display: none;">testprotocollink</a>
    

    虽然有点老套,但很管用。不幸的是,Firefox版本仍然会弹出默认警报,当您尝试访问具有未知协议的链接时会出现该警报,但它会在警报解除后运行您的代码。

        11
  •  1
  •   Megha    14 年前

    这是微软支持部门为IE推荐的一种方法

    http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx#related_topics

    “如果您对安装在用户计算机上的二进制文件有某种控制,那么检查UA-in脚本似乎是一种相关的方法: “——M$支持

    每个网页都可以访问userAgent字符串,如果您删除一个自定义的post platform值,则可以使用导航器.用户代理很简单。

    对于FF和Chrome,只需在没有任何检测的情况下启动自定义协议。让用户告诉你他看到了什么。 对于Safari,:(还没有答案

        12
  •  0
  •   ken    15 年前

    这不是一个简单的任务;一个选项可能是使用签名代码,您可以利用它访问注册表和/或文件系统(请注意,这是一个 very expensive 选项)。代码签名也没有统一的API或规范,因此需要为每个目标浏览器生成特定的代码。支持的噩梦。

    而且,我知道 Steam ,游戏系统似乎也没有解决这个问题。

        13
  •  0
  •   sethcall    11 年前

    1. 用户单击链接,尝试启动应用程序。独一无二的 标识符放在链接中,以便将其传递给 应用程序启动时。Web应用程序显示一个旋转器或类似的东西。
    2. 然后网页开始检查
    3. 启动时,您的应用程序会向您的web应用程序发送HTTP post 带有唯一标识符,表示存在。
    4. 要么网页看到应用程序最终启动了,要么继续使用“请下载”页面。