实时捕获WScript.Shell的输出

时间:2012-06-16 08:58:04

标签: windows command-line vbscript hta jscript

我在.hta文件中使用JScript(与VBScript相同),打开一个新的shell命令并捕获其输出。这是我在谷歌搜索后到目前为止所得到的:

var shell = new ActiveXObject("WScript.Shell")
var e = shell.Exec("%comspec% /c ping google.com 2>&1 ") 
while(!e.StdOut.AtEndofStream) {
    var line = e.StdOut.ReadLine()
    document.getElementById('log').value = line
}

这很有效。但是,它不是异步的。 while循环导致我的.hta接口刚刚阻塞(UI变得无法使用),直到shell命令完成。如果我删除while loopshell.Exec命令似乎没有阻止,所以问题出在循环内的某个地方。

我认为阻塞问题只会发生,因为我在.hta环境中。如果我使用cscript.exe

通过命令行运行我的脚本,似乎不会发生这种情况

如何实时避免阻塞行为并访问命令输出?

2 个答案:

答案 0 :(得分:1)

你可能需要反复调用setTimeOutfake a background thread而只需要在计时器回调中做少量工作......

答案 1 :(得分:0)

正如Anders所指出的,你需要实现伪多线程策略,因为 您的GUI不会对任何用户输入做出反应,只要JScript代码(任何函数) 被执行。

我使用setInterval()而不是setTimeout(),原因是here

这个.hta

<html>
 <head>
  <title>Ping HTA (JScript)</title>
  <HTA:APPLICATION
    APPLICATIONNAME="PingHTA"
  >
  <SCRIPT Language="JScript" src="ping.js"></SCRIPT>
 </head>
 <body onload="onLoadBody()">
  <form name="anonymous">
   <h2>Ping HTA (JScript)</h2>
   <hr>
   <input id="bttStartPing" type="BUTTON" value="StartPing" onclick="startPing()">
   <hr>
   <textarea id="taDisplay" rows="25" cols="80"></textarea>
  </form>
 </body>
</html>

和.js

//= app globals
g_sCmd      = '%comspec% /c ping.exe /n 8 google.com 2>&1';
g_taDisplay = null;
g_PSIHandle = 0;
g_PSILock   = false;
g_oExec     = null;

//= prep for log
function onLoadBody() {
  g_taDisplay = window.document.getElementById("taDisplay");
  log("OnLoadBody() done.");
}

//= log
function log(msg) {
  g_taDisplay.value = new Date().toString() + "\n   " + msg + "\n" + g_taDisplay.value;
}

//= start job
function startPing() {
  if (0 == g_PSIHandle) {
     g_PSIHandle = setInterval(stepPing, 100);
     log('setInterval(stepPing, 100)');
     g_oExec = new ActiveXObject("WScript.Shell").Exec(g_sCmd);
     log("started " + g_sCmd);
  } else {
     log('***** Ping is running!');
  }
}

//= one step of job
function stepPing() {
  if (! g_PSILock) {
     g_PSILock = true;
     if (null !== g_oExec) {
        if (g_oExec.StdOut.AtEndofStream) {
           clearInterval(g_PSIHandle);
           g_PSIHandle = 0;
           log('StdOut.AtEndofStream, terminate ping');
           g_oExec.Terminate();
           g_oExec = null;
        } else {
           log(g_oExec.StdOut.ReadLine());
        }
     }
     g_PSILock = false;
  }
}

应该证明:

  1. 在.hta中使用.Exec会打开一个shell窗口(对于某些人来说) 这是一个不合格者)
  2. 之前.hta将开始拾取ping输出行 流程终止
  3. 在进程运行时单击按钮将散布 ping输出的消息(虽然反应感觉 呆滞)
  4. 生产版本必须花费更多精力进行交易 与.Exec的可能状态和错误处理。

    为此,请开始您的研究here并谷歌搜索“WshScriptExec对象”。