使用Windows脚本宿主从WshShell.Exec捕获输出 [英] Capturing output from WshShell.Exec using Windows Script Host

查看:177
本文介绍了使用Windows脚本宿主从WshShell.Exec捕获输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wrote the following two functions, and call the second ("callAndWait") from JavaScript running inside Windows Script Host. My overall intent is to call one command line program from another. That is, I'm running the initial scripting using cscript, and then trying to run something else (Ant) from that script.

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);
  }
 }

}

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

Unfortunately, when I run my program, I don't get immediate feedback about what the called program is doing. Instead, the output seems to come in fits and starts, sometimes waiting until the original program has finished, and sometimes it appears to have deadlocked. What I really want to do is have the spawned process actually share the same StdOut as the calling process, but I don't see a way to do that. Just setting oExec.StdOut = WScript.StdOut doesn't work.

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

Is there an alternate way to spawn processes that will share the StdOut & StdErr of the launching process? I tried using "WshShell.Run(), but that gives me a "permission denied" error. That's problematic, because I don't want to have to tell my clients to change how their Windows environment is configured just to run my program.

我该怎么办?

推荐答案

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

You cannot read from StdErr and StdOut in the script engine in this way, as there is no non-blocking IO as Code Master Bob says. If the called process fills up the buffer (about 4KB) on StdErr while you are attempting to read from StdOut, or vice-versa, then you will deadlock/hang. You will starve while waiting for StdOut and it will block waiting for you to read from StdErr.

实际的解决方案是重定向StdErr像这样的StdOut:

The practical solution is to redirect StdErr to StdOut like this:

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

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

In other words, what gets passed to CreateProcess is this:

CMD /S /C " "c:\Path\To\prog.exe" Argument1 argument2 2>&1 "

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

This invokes CMD.EXE, which interprets the command line. /S /C invokes a special parsing rule so that the first and last quote are stripped off, and the remainder used as-is and executed by CMD.EXE. So CMD.EXE executes this:

"c:\Path\To\prog.exe" Argument1 argument2 2>&1

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

The incantation 2>&1 redirects prog.exe's StdErr to StdOut. CMD.EXE will propagate the exit code.

现在可以通过读取StdOut并忽略StdErr来成功。

You can now succeed by reading from StdOut and ignoring StdErr.

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

The downside is that the StdErr and StdOut output get mixed together. As long as they are recognisable you can probably work with this.

这篇关于使用Windows脚本宿主从WshShell.Exec捕获输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆