使用Windows脚本宿主从WshShell.Exec捕获输出

Eri*_*son 11 javascript stdout wsh

我编写了以下两个函数,并从Windows Script Host中运行的JavaScript调用第二个函数("callAndWait").我的总体意图是从另一个调用一个命令行程序.也就是说,我正在使用cscript运行初始脚本,然后尝试从该脚本运行其他东西(Ant).

function readAllFromAny(oExec)
{
     if (!oExec.StdOut.AtEndOfStream)
          return oExec.StdOut.ReadLine();

     if (!oExec.StdErr.AtEndOfStream)
          return "STDERR: " + oExec.StdErr.ReadLine();

     return -1;
}

// Execute a command line function....
function callAndWait(execStr) {
 var oExec = WshShell.Exec(execStr);
  while (oExec.Status == 0)
 {
  WScript.Sleep(100);
  var output;
  while ( (output = readAllFromAny(oExec)) != -1) {
   WScript.StdOut.WriteLine(output);
  }
 }

}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我运行我的程序时,我没有得到关于被调用程序正在做什么的立即反馈.相反,输出似乎进入适合和开始,有时等到原始程序完成,有时似乎已经死锁.我真正想要做的是让生成的进程实际上与调用进程共享相同的StdOut,但我没有看到这样做的方法.只是设置oExec.StdOut = WScript.StdOut不起作用.

是否有另一种方法来生成将共享启动过程的StdOut和StdErr的进程?我尝试使用"WshShell.Run(),但这给了我一个"权限被拒绝"错误.这是有问题的,因为我不想告诉我的客户改变他们的Windows环境配置只是为了运行我的程序.

我能做什么?

Ben*_*Ben 11

您无法以这种方式从脚本引擎中读取StdErr和StdOut,因为没有像Code Master Bob所说的非阻塞IO.如果被调用的进程在您尝试从StdOut读取时填充了StdErr上的缓冲区(大约4KB),反之亦然,那么您将死锁/挂起.在等待StdOut时你会饿死它会阻止你等待你从StdErr读取.

实际的解决方案是将StdErr重定向到StdOut,如下所示:

sCommandLine = """c:\Path\To\prog.exe"" Argument1 argument2"
Dim oExec
Set oExec = WshShell.Exec("CMD /S /C "" " & sCommandLine & " 2>&1 """)
Run Code Online (Sandbox Code Playgroud)

换句话说,传递给CreateProcess的是:

CMD /S /C " "c:\Path\To\prog.exe" Argument1 argument2 2>&1 "
Run Code Online (Sandbox Code Playgroud)

这将调用CMD.EXE,它解释命令行./S /C调用一个特殊的解析规则,以便剥离第一个和最后一个引号,其余部分按原样使用并由CMD.EXE执行.所以CMD.EXE执行这个:

"c:\Path\To\prog.exe" Argument1 argument2 2>&1
Run Code Online (Sandbox Code Playgroud)

咒语2>&1prog.exeStdErr 重定向到StdOut.CMD.EXE将传播退出代码.

现在,您可以通过阅读StdOut并忽略StdErr来取得成功.

缺点是StdErr和StdOut输出混合在一起.只要它们是可识别的,你就可以使用它.


And*_*ers 1

是的,Exec 函数在终端输出方面似乎被破坏了。

我一直在使用一个类似的函数function ConsumeStd(e) {WScript.StdOut.Write(e.StdOut.ReadAll());WScript.StdErr.Write(e.StdErr.ReadAll());},我在与您类似的循环中调用该函数。不确定检查 EOF 和逐行读取是好是坏。