10

我有一个旧的 html 页面,它创建一个脚本文件并使用以下命令执行它:

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

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

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

我创建了启动 VBScript 文件的自定义 URL 协议,如下所示:

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 服务器提供服务,它甚至无法想象管理如此复杂的脚本。

4

3 回答 3

4

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

我也希望自定义 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 协议限制的最佳方法。我也希望这不是必需的。这确实有效并且运作良好。

您提到了 Dominos,所以您可能需要在 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 地址和令牌检查凭据,如果全部对齐,则返回 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. 服务器将密钥返回给ajax回调函数
  5. 现在客户端有一个单一的使用密钥并调用传递密钥的 url 模式
  6. vbscript 对服务器进行 https 获取并传递密钥
  7. 服务器将数据返回到 vbscript

有点啰嗦。一旦编码,它将像魅力一样工作。

我能看到的唯一另一种选择是使用以下方式将表单数据复制到剪贴板:http: //zeroclipboard.org/

然后在 vbscript 中查看是否可以像这样读取剪贴板: 使用 VBScript中的剪贴板

于 2014-05-06T00:19:01.283 回答
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 透明/隐藏。

于 2014-05-06T01:19:05.383 回答
0

您可能不喜欢这个答案,但我过去使用过这种方法并且它有效。

与其依赖 ActiveX,不如考虑使用 Java Applet 和 JNI。

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

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

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

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

PS文章确实很老,但是概念保持不变。

于 2014-05-05T20:43:24.343 回答