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


82

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

http://

mailto://

custom://

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

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

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

感谢您提出的任何想法。


5
我认为这只能在Chrome(例如XPCOM,ActiveX等)代码中实现。否则,这将是一个隐私问题(“我们检测到您使用了Eudora。立即切换到FooMail!”)。但请澄清一下浏览器(S)/ OS(ES)你感兴趣的
马修•富兰琛

1
很好,但是我很高兴知道已经注册了一些东西来处理我的专有协议acsfs:// Windows IE,FireFox和理想的Safari
Chris Craft 2009年

您解决已经解决了这个问题吗?
jstuardo

Answers:


35

这将是一个非常非常 哈克做到这样......但将这项工作?

  • 正常放置链接...
  • 但是将一个onclick处理程序附加到该处理程序上,该处理程序将设置计时器并为该窗口添加一个onblur处理程序
  • (理论上)如果浏览器处理了链接(应用程序X),则会加载从窗口窃取焦点的行为...
  • 如果onblur事件触发,请清除计时器...
  • 否则,请在3-5秒内触发超时...,并通知用户“嗯,您似乎尚未安装Mega Uber Cool Application ...您现在要安装它吗?(确定)(取消)”

远非防弹...但可能有所帮助?


1
:D这是一个聪明的主意。似乎会有一种方法,因为这似乎很普遍。
克里斯·克拉夫特

2
在Mac上的Firefox(可能是更多浏览器)中,即使具有自定义协议的应用程序无法启动,窗口也会失去焦点并触发模糊处理。
quano

对于Chrome来说,这是一个不错的解决方案,因为它对协议没有任何类型的错误处理。这已与检测其他浏览器结合使用:rajeshsegu.com/2012/09/browser-detect-custom-protocols/…–
Fillip Peyton

协议检测最近一直是头疼的主要问题。;)上面的方法似乎有点用...使用rajeshsegu.com/fun/code/browser/detect.html上的rajesh实时示例,我正在Chrome中获得“ true”。但是,如果我进行重构以使没有result()函数(该函数又使用警报框-阻塞调用),而只返回一个布尔值,那我就错了。我以某种方式感觉到阻止警报也是一种以某种方式强制计时的恶意方式...任何见识,@ scunliffe?
格雷格·佩蒂特

该方法在Chrome中有效,除非用户选择使用Win8记住自己的答案并且没有该应用程序。在这种情况下,即使应用程序无法启动,也会发生模糊事件
Paul Haggo 2015年

18

没有很好的跨浏览器方法来做到这一点。在Win8 +的IE10 +中,msLaunchUriapi使您可以启动协议,如下所示:

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



6
msLaunchUri仅适用于Windows 8+。
EricLaw 2014年

链接已死。
秋朗

16

HTML5定义了自定义方案和内容处理程序(据我所知,Firefox是迄今为止唯一的实现程序),但是不幸的是,目前尚无办法检查处理程序是否已存在-已提出该处理程序,但没有后续措施。这似乎是有效使用自定义处理程序的一项关键功能,我们开发人员应注意此问题,以使其实现。


13

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

在iTunes模型中,Apple向其服务器提供url,然后这些URL提供运行某些javascript的页面:

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

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

如果安装了插件,则可以合理地确定重定向到应用程序特定的URL将会成功。


2
这应该是最可靠的解决方案。但是我的意思是,您需要为大多数浏览器安装并创建一个插件,这有点棘手。我可以更加用户友好,从而能够将用户重定向到下载页面。
Natim 2010年

为什么不使用这里提到的FireBreath?stackoverflow.com/a/14758085/427793
swdev 2014年

10

最容易解决的问题是第一次问用户。

每个示例使用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/'

饼干可以每天清除干净。有没有更好的方法可以制作基于Flash的cookie?

好吧,如果删除Cookie,只会再次提示用户。
Natim 2014年

5

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

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

  2. 尝试打开程序,然后传递意图数据。

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

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

我还没有尝试过这种方法,只是想到了。


4

我能够最终得到一个跨浏览器(浏览器32,火狐27,IE 11,Safari浏览器6)溶液用工作的组合和超简单的Safari扩展。在这个问题另一个问题中,已经以一种或另一种方式提到了许多这种解决方案。

这是脚本:

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);
    }
}

Safari扩展很容易实现。它由单行注入脚本组成:

myinject.js:

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

然后在网页JavaScript中,您需要首先注册消息事件并在收到消息时设置一个标志:

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

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

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


它不适用于IE。应该如何运作?myWindow.location.href;src该窗口中定义的iframe之间的连接是什么?它应该引发异常吗?不管是否支持自定义协议,都不会。
Burjua 2015年

3

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

如果您做了类似从Sourceforge下载文件时发生的事情该怎么办?假设您要打开myapp:// something。与其简单地创建一个链接,不如创建到另一个通过HTTP访问的HTML页面的链接。然后,在该页面上,说您正在尝试为他们打开应用程序。如果不起作用,他们需要安装您的应用程序,可以通过单击您提供的链接来完成。如果它确实有效,那么您就一切准备就绪。


4
提示这将是无用的。对我来说似乎很明显,能够有条件地显示启动或下载链接-甚至在单击链接时有条件地启动或下载,都比告诉用户他们首先需要安装要好。
StuartQ 2015年

3

您可以尝试如下操作:

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
        }
    }
}

不,在Firefox 27中不起作用。(未在其他浏览器中进行测试)
Blaise 2014年

1
不起作用-已在Windows 7,IE,Firefox,Opera,Chrome中测试过

1

我正在尝试做类似的事情,但我发现了一个可与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>

这有点hacky,但是可以用。不幸的是,当您尝试访问具有未知协议的链接时,Firefox版本仍会弹出默认警报,但是该警报将在警报消失后运行。


1
我发现我仍然收到“ Firefox不知道如何打开该地址的信息,因为协议(tel)与任何程序都没有关联。” 捕获块之前的消息
Deebster 2010年

6
protocolLong仅返回“已知”协议(文件:,mailto:,gopher:,ftp:,http:,https :、新闻:)的结果,而不返回其他应用程序协议的结果。
EricLaw

1

这是Microsoft支持的IE建议的方法

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

“如果对用户计算机上安装的二进制文件有一定的控制权,则检查脚本中的UA似乎是一种相关方法:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Internet Settings \ 5.0 \ User Agent \ Post Platform”-由M $支持

每个网页都可以访问userAgent字符串,如果您删除自定义的发布平台值,则使用navigator.userAgent在javascript中进行检测非常简单。

幸运的是,当单击带有自定义协议的链接并且用户计算机上未安装该协议时,其他主要浏览器(如Firefox和Chrome)(除非Safari :(),不会引发“找不到页面”)错误。 ,任何在看不见的框架中单击或捕获javascript错误的技巧均不起作用,最终以丑陋的“无法显示网页”错误告终。我们在本例中使用的技巧是告知具有浏览器特定图像的用户单击自定义协议链接将打开一个应用程序,如果他们没有找到打开的应用程序,则可以单击“安装”页面。就XD而言,这种wprks方式比IE的ActiveX方法要好。对于FF和Chrome,请继续并在没有任何检测的情况下启动自定义协议。让用户告诉您所看到的内容。对于Safari ,:(尚无答案


用户代理扩展是一种常见的但有问题的方法。blogs.msdn.com/b/ieinternals/archive/2009/10/08/...
EricLaw

0

这不是一项艰巨的任务。一种选择是使用签名代码,您可以利用它来访问注册表和/或文件系统(请注意,这是非常昂贵的选择)。也没有统一的API或代码签名规范,因此您将需要为每个目标浏览器生成特定的代码。一场噩梦。

另外,我知道游戏内容交付系统Steam似乎也没有解决此问题。


2
签名的代码应该由与处理custom://的应用程序一起安装的证书签名,因此不需要像verisign这样的人签名的真正昂贵的应用程序证书。
WhyNotHugo 2010年

0

这是另一个棘手的答案,可能需要对应用程序进行修改(希望是轻巧的),以便在启动时“回拨电话”。

  1. 用户单击链接,尝试启动该应用程序。链接中会放置一个唯一的标识符,以便在启动时将其传递给应用程序。Web应用程序显示微调器或类似性质的东西。
  2. 然后,网页开始从具有相同唯一ID的应用程序检查“应用程序电话回家”事件。
  3. 启动后,您的应用程序会使用唯一标识符对您的Web应用程序进行HTTP发布,以指示其状态。
  4. 该网页要么看到应用程序最终启动,要么继续运行“请下载”页面。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.