最简单的跨浏览器检查协议处理程序是否已注册

41
当用户点击自定义协议的链接(如myapp://superlink),我需要启动一个应用程序或允许用户下载并运行配置应用程序。我正在寻找一种跨浏览器的方法来检查自定义协议是否已注册。我曾尝试通过在服务器端检查用户代理(针对IE)来确定这一点。

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform] "myapp"=""

发送。
`....NET CLR 3.0.30729; .NET4.0C; .NET4.0E; InfoPath.3; **myapp**`

作为用户代理

这是一个好的、干净的、易于配置的方法:

只需下载.reg文件并运行它或通过ms windows策略传播即可。

我无法解决Chrome和Firefox的问题。

有没有客户端解决方案(使用js)?

我的环境:IE8+,Chrome(最新版),Firefox(最新版)


1
如果您使用示例协议发送AJAX请求,然后测试响应会发生什么? - Lee Taylor
1
@LeeTaylor - 那样做行不通。CORS 问题会出现。也许这个链接可以帮到你 https://dev59.com/S3RA5IYBdhLWcg3www3D - Jibi Abraham
如果 (!navigator.isProtocolHandlerRegistered("myapp", url)) { navigator.registerProtocolHandler("myapp", url, "Fake Protocol"); } - dandavis
嗨!这个超级链接实际上在客户端启动我们的二进制应用程序(.exe),或下载安装程序,因此不能使用任何ajax。 - jonny
我最初使用了habsq的代码,但在某些IE版本上失败了,然后我尝试了https://gist.github.com/aaronk6/d801d750f14ac31845e8,它可以工作! - Qiulang
6个回答

29

有一个老套路,它从未让我失望。

你需要的核心功能是setTimeout。我会详细告诉你:

setTimeout(function() {
  window.location = "http://itunes.com/app/yourapplocation";
}, 200);

// once you do the custom-uri, it should properly execute the handler, otherwise, the settimeout that you set before will kick in
window.location = "myapp://superlink";

现在你提到可能是一个链接或多个链接,所以我编写了这个方便易用的函数:

HTML 代码

<a href="myapp://superlink" data-href-alt="http://itunes.com/app/yourapplocation">Click here</a>

JS 代码

$("a[href*='myapp://']").click(function(e)
{
  var el = $(this);
  setTimeout(function() {
    window.location = el.data("data-href-alt");
  }, 200);

  // once you do the custom-uri, it should properly execute the handler, otherwise, the settimeout that you set before will kick in
  window.location = el.data("href");

  e.preventDefault();
});

希望这能对您有所帮助 :)


我真的很喜欢你的jQuery代码,这是一个不错且简单的修复方法。也许将其捆绑成一个jQuery插件会更有价值,肯定有很多人会想使用它。 - Barkermn01
1
嗨!这个超链接实际上会在客户端启动我们的二进制应用程序(.exe),或者下载安装程序,因此无法使用ajax。 - jonny
3
这个解决方案对我没有用。它会打开 href 和 alt-href。我想用 jsFiddle 向你展示,但是当你设置 window.location 时,它不允许。 - user773737
似乎在Windows 10版本1903上失败了。 - Jeff
火狐浏览器现在会弹出一个窗口询问是否允许打开自定义协议。所以这最终会重定向到备用网址。 - Gaurang Tandon

20

我遇到了一个类似的问题,需要检查自定义协议是否已经注册(这将打开一个可执行文件),否则要打开下载页面或者执行其他操作。不幸的是,由于每个浏览器的行为不同,没有简单的方法来处理这个问题。我尝试收集所有信息,并提出一个通用的库,你可以看一下:

https://github.com/ismailhabib/custom-protocol-detection

注:对于非Windows 8 IE的解决方案相当丑陋,但我找不到更好的解决方案。


2
到目前为止,我测试过的浏览器中,这似乎非常有效。干得好! - rolledback
非常喜欢,非常感谢。解决方案很出色! - Ali Jamal
我正在尝试使用同样的库,但它对我不起作用。无论URI是成功加载还是失败,onBlur都不会触发。var timeout = setTimeout 这个函数总是触发。如果你遇到过类似问题,有什么想法吗? - Ambuj Khanna

10

kororo的解决方案对我来说不起作用,所以我使用了这个稍微修改过的解决方案。

<html>
<a id="link">Click Me</a>
<script>
var link = document.getElementById('link');
var timeout;
window.addEventListener('blur',function(e){
    window.clearTimeout(timeout);
})

link.addEventListener('click', function(e) { 

    timeout = window.setTimeout(function() {
      console.log('timeout');
      window.location = "https://myapp.net";
    }, 1000);

    window.location = "myapp://";
    e.preventDefault();
});
</script>
</html>

8
请注意,截至2020年2月,似乎没有一种可行的方法来实现这一点。仅考虑Chrome,@kororo或@habsq的解决方案目前都不起作用。原因是我们试图通过检查URL协议处理程序是否存在来实现的内容,实际上被一些人视为安全风险。
所以我的建议是不要执意尝试使其工作。 如果您尝试让它工作,最好的情况是成功,直到某个浏览器删除了允许您“黑客”方式检查url协议的机制,然后您又回到了起点。
这里更简单的方法是像很多大型网站一样,在您的页面上使用JavaScript并显示类似以下内容:
window.location = "myprotocol://asdf";

这将有可能起作用或失败,并在页面上显示一条消息,大概意思是:“如果此次操作未能成功,请下载我们的软件,链接如下”。


1
另外需要补充的是:在应用程序中使用具有唯一浏览器标识符的回调系统,以通知服务器协议已被触发,因此无需显示下载提示。 - Yakov .P
@Yakov.P 是的,我也这样想,但是在我看来,这里有几个困难,阻止了这成为一个真正好的想法。1. 如果有人第一次错过了下载提示,那么他们下次就没有安装程序的方法了。2. 如果有人使用不同的浏览器,那么这个检查将无法通过。3. 如果有人下载了该工具并卸载了它,他们将没有重新安装的方法。 - Jack
1
它可以每次检查,不需要一次性然后再也不提示。 (如果程序被卸载,它将无法运行,也不会向服务器发送信号,从而产生另一个提示) - Yakov .P

2

更新Korono的回答,这对我有用:

$(function() {
    var timeIndex;
    $("a[href*='myapp://']").blur(function(e)
    {
        clearTimeout(timeIndex);
    });

    $("a[href*='myapp://']").click(function(e)
    {
      var el = $(this);
      timeIndex = setTimeout(function() {
        window.location = el.attr("data-href-alt");
      }, 200);

      // once you do the custom-uri, it should properly execute the handler, otherwise, the settimeout that you set before will kick in
      window.location = el.attr("href");
      e.preventDefault();
    });
});

-1

你好

安装ismailhabib/custom-protocol-detection

通过包含这个JS文件protocolcheck.js

然后编写类似以下的代码

<div id="protocol" href="myprotocol:johndoe@somewhere.com">Check Protocol</div>

<script>
        $("#protocol").click(function (event) {
            protocolCheck($(this).attr("href"), function () {
                    alert("protocol not recognized");
                });
            event.preventDefault ? event.preventDefault() : event.returnValue = false;
        });
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接