【问题标题】:How to start two or more custom URL Protocol from Javascript如何从 Javascript 启动两个或多个自定义 URL 协议
【发布时间】:2014-05-30 14:02:12
【问题描述】:

我有一个旧的 html 页面,它创建一个脚本文件并使用:

fsoObject = new ActiveXObject("Scripting.FileSystemObject")
wshObject = new ActiveXObject("WScript.Shell")

我正在尝试对其进行修改,使其也可以在其他浏览器中使用。如果您知道答案,请停止阅读,请回答。如果没有快速回答,这里是我尝试的描述。我成功地完成了这项工作,但前提是脚本少于 2000 个字符。对于超过 2000 个字符的脚本,我需要帮助。

该网页仅供内部使用,因此我可以轻松地在每台运行网络驱动器中的 VBScript 文件的计算机上创建自定义 URL 协议。

我创建了我的custom URL Protocol,它可以像这样启动一个 VBScript 文件:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\MyUrlProtocol]
"URL Protocol"=""
@="Url:MyUrlProtocol"
"UseOriginalUrlEncoding"=dword:00000001

[HKEY_CLASSES_ROOT\MyUrlProtocol\DefaultIcon]
@="C:\\Windows\\System32\\WScript.exe"

[HKEY_CLASSES_ROOT\MyUrlProtocol\shell]

[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open]

[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open\command]
@="C:\\Windows\\System32\\WScript.exe \"X:\\MyUrlProtocol.vbs\" \"%1\""

MyUrlProtocol.vbs 我有这个:

MsgBox "The length of the link is " & Len(WScript.Arguments(0)) & " characters"
MsgBox "The content of the link is: " & WScript.Arguments(0)

当我点击 <a href="MyUrlProtocol:test" id="test">click me</a> 时,我看到两条消息,所以一切正常(在 Windows 7 中使用 Chrome 和 IE 进行了测试。)

当我执行document.getElementById("test").click()时它也有效

我认为这可能是解决方案:我会将脚本的文本传递给 VBS 静态脚本,该脚本将创建动态脚本并运行它,但是使用这个系统我不能传递超过 ~2000 个字符。

所以我尝试将脚本的文本分割成小于 2000 个字符的块,并模拟点击链接的几次,但只有第一个有效。

所以我尝试使用 xmlhttp.open("GET","MyUrlProtocol:test",false);,但 Chrome 显示为 Cross origin requests are only supported for HTTP

是否可以通过自定义 URL 协议将超过 2000 个字符传递给 VBScript 脚本?

如果不是,是否可以依次调用多个自定义 URL 协议?

如果没有,是否有另一种方法来创建脚本文件并从 Javascript 运行它?

编辑 1

我找到了一个解决方案,但在 Chrome 中只有在它喜欢的时候才有效,所以我回到了原点。

以下代码在 IE 中执行脚本 4 次(正确),但在 Chrome 中只运行第一次执行。

如果我将其更改为delay += 2000,那么 Chrome 通常会运行脚本 2 次,但有时会运行 1 次,有时会运行 3 次甚至 4 次。

如果我将其更改为delay += 10000,那么它通常会运行脚本 4 次,但有时会错过一次。

在 Chrome 和 IE 中,该函数总是执行 4 次。奇怪的是sr.click()有时什么都不做,函数继续执行。

<HTML>
<HEAD>
  <script>
    var delay;

    function runScript(text) {
      setTimeout(function(){runScript2(text)}, delay);
      delay += 100;
    }

    function runScript2(text) {
      var sr = document.getElementById('scriptRunner');
      sr.href='intelliclad:'+text;
      sr.click();
    }

    function test(){
      delay = 0;
      runScript("uno");
      runScript("due");
      runScript("tre");
      runScript("quattro");
    }
  </script>
</HEAD>
<BODY>
  <input type="button" value="Run test" onclick="test()">
  <a href="nothing yet" id="scriptRunner">scriptRunner</a>
</BODY>
</HMTL>

编辑 2

我尝试了 Luke 的建议,即从回调内部设置下一个超时,但没有任何改变(IE 始终有效,Chrome 随时可用)。

这是新代码:

var scripts;
var delay = 2000;

function runScript() {
  var sr = document.getElementById('scriptRunner');
  sr.href = 'intelliclad:' + scripts.shift();
  sr.click();

  if(scripts.length)
    setTimeout(function() {runScript()}, delay);
}

function test(){
  scripts = ["uno", "due", "tre", "quattro"];
  runScript();
}

一些背景:页面要求面板的形状,可以是几个参数[nfaces=1, shape1='square', width1=100],也可以是多面、多槽、多紧固件等面板的数百个参数。询问所有参数后为我们的内部 3D CAD(可能大于 20KB)生成一个脚本,然后启动 CAD 并要求执行该脚本。

我想在客户端做所有事情,因为页面由 Domino Web 服务器提供服务,它甚至无法管理如此复杂的脚本。

【问题讨论】:

标签: javascript html onclick url-protocol


【解决方案1】:

我没有阅读你的整个帖子...有一个答案:

我也希望自定义 url 协议可以处理长 url。他们根本没有。 IE 更糟糕,因为某些操作系统只接受 800 个字符。

所以,解决方案如下:

For long urls, only pass a single use token.   The vbscript uses the token 
and does a url get to your web server to get all of the data.

这是我能够成功传递大量数据的唯一方法。如果您找到更清晰的解决方案,请记得在此处发布。

更新:

请注意,这是我发现的处理 url 协议限制的最佳方法。我也希望这不是必需的。这确实有效并且效果很好。

您提到了多米诺骨牌,所以您可能需要在 POS 环境中使用某些东西...我创建了一个基于 Web 的 POS 系统,因此我们可能会面临很多相同的问题。

假设您想要一个自定义 url 将 pdf 打印到默认打印机,而不会出现烦人的弹出窗口。我们需要每天这样做数千次......

  1. 在构建网页时,添加打印按钮,按下该按钮会调用自定义 url:myproto://printpdf?id=12345&token=onetimetoken

  2. 这将在本地桌面上执行您的 vbscript

  3. 在您的 vbscript 中,解析参数并做出反应。在这种情况下,您的命令是 printpdf,id 是 123456,并且您有一个一次性令牌。

  4. 将 vb 脚本发送到 https 访问:https://mydomain.com/APIs/printpdf.whatever?id=12345&key=onetimetoken

  5. 根据ip地址和token检查凭证,如果全部对齐,则返回pdf的内容(您可能希望将pdf转换为字节数组字符串)

  6. 现在 vbscript 有了 pdf,将其组装并写入临时文件夹,然后执行静默 pdf 打印命令(我使用 Sumatra PDF http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader.html

  7. 任务完成。

由于我确实知道您在自定义 url 和一般工作流程中要做什么,所以我只能描述我是如何解决排序 url 问题的。

使用这种技术,可能性是无限的。您可以完全控制运行 Web 浏览器的本地计算机,您有一个一次性使用令牌,它授予对 Web API 的访问权限,可以返回您编程的任何类型的信息。

如果你愿意,你可以编写一个自定义 url 协议来打开比萨烤箱 :)

如果您无法创建正在侦听 vbscript 的 get 请求的服务器端代码,那么这将不起作用。

您也许可以使用剪贴板将数据从浏览器传递到 vbscript。

更新 2:

由于在这种情况下数据在客户端上(一个表单可以定义数百个参数),服务器 API 不知道如何响应 vb 脚本请求。所以上面描述的工作流程之前必须有这两个步骤:

  1. onkeypress事件执行提交将当前参数发送到服务器

  2. 服务器回复刷新后的表单,在正文onload 中添加对使用另一个提交来调用自定义 url 的函数的调用,如上面列出的第 1 点所述。

    李>

更新 3: stenci,您添加的内容(在更新 2 中)将起作用。我会这样做:

  1. 用户按下按钮说我已经完成了对表单的编辑
  2. ajax 将表单发布到服务器
  3. 服务器保存数据并将唯一密钥附加到数据存储区
  4. 服务器将key返回给ajax回调函数
  5. 现在客户端有一个单次使用密钥并调用传递密钥的 url 架构
  6. vbscript 通过 https 访问服务器并传递密钥
  7. 服务器将数据返回给vbscript

有点啰嗦。一旦编码,它就会像魅力一样发挥作用。

我能看到的唯一其他选择是将表单数据复制到剪贴板,使用类似:http://zeroclipboard.org/

然后在 vbscript 中查看是否可以读取剪贴板,例如:Use clipboard from VBScript

【讨论】:

  • 往返非常困难,因为有一个 Domino Web 服务器,它只做它喜欢的事情,而不是我喜欢的事情。加上往返很慢。我需要更多细节。它是如何工作的?参数在浏览器上,而不是在服务器上。浏览器是否应该提交所有参数并且服务器返回的页面应该在onload事件中启动自定义URL?
  • 是的,它是一个往返,它是 20-60 毫秒,具体取决于网络,这太糟糕了——它足够快,我的用户没有任何问题。我将更新我的答案以描述我如何处理这个问题。为了在您的环境中工作,您需要能够编写服务器端代码。最终,您正在为您的自定义协议创建一个 API。
  • 假设服务器具有完成工作所需的信息,您的想法是可行的。在我的情况下,数据在客户端上。所以我需要两次同步往返。评论太难描述了,我添加了一个更新。请让我知道您的想法并随时编辑...您自己的答案!
  • 剪贴板,为什么没想到!!!在开始在服务器端工作之前,我会调查这条路。谢谢。
  • 如果你能分享你的发现,那就太好了。我对使用剪贴板犹豫不决,因为似乎必须安装 Flash,或者每次 javascript 累了访问剪贴板时都会提示用户——这可能是不正确的。如果您愿意分享您的发现,请分享。
【解决方案2】:

为每个实例创建一个 iFrame 怎么样? 像这样的:

function runScript(text) {
  var iframe = document.createElement('iframe');
  iframe.src = 'intelliclad:'+text;
  document.body.appendChild(iframe);
}

function test(){
  runScript("uno");
  runScript("due");
  runScript("tre");
  runScript("quattro");
}

然后您可以使用 css 样式使这些 iframe 透明/隐藏。

【讨论】:

    【解决方案3】:

    你可能不喜欢这个答案,但我过去曾使用过这种方法,它很有效。

    考虑使用 Java Applet 和 JNI,而不是依赖 ActiveX。

    基本上,您必须确保要运行的本机脚本以及 JNI 包装器在您的客户端计算机上可用。

    小程序必须至少是自签名的,浏览器才能允许它加载和访问本机库。加载 JNI 库后,您可以轻松地从页面/小程序调用方法。

    作为使用 Java 的结果,您可以为 Windows 和 linux 客户端使用相同的小程序,当然前提是您在各自的客户端上存在本机库。

    本系列文章正是针对你的问题:http://www.javaworld.com/article/2076775/java-security/escape-the-sandbox--access-native-methods-from-an-applet.html

    P.S 文章确实老了,但概念没变。

    【讨论】:

    • 通过下载active x插件在mozilla和google chrome中也支持active x
    • 我并不是在暗示 ActiveX 不兼容跨浏览器,事实上考虑到 OP 在受控环境中部署它,跨浏览器/平台兼容性可能甚至不是问题。
    • 我没想到电脑上可能会有不同的平台,但这会是个问题。你是对的
    • 有人喜欢java小程序吗?
    • 不...这个答案很好...一个java小程序可以完成这项工作,对它们进行编码对某些人(比如我)来说只是一种痛苦。我曾经使用 jzebra 打印小程序来驱动条形码打印机code.google.com/p/jzebra 它加载缓慢,运行缓慢,当 Java 45 Update 7 发布时,它破坏了小程序,因为现在小程序需要代码签名(或其他东西)。这让我发疯了,因为我的用户突然不能再打印条形码了。我的解决方案是创建一个自定义 url 协议——效果很好..非常快速且易于编码并且始终有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 2019-12-20
    • 2020-08-31
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多