gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 02:19:09 26 4
gpt4 key购买 nike

我编写了以下两个函数,并从在 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);
}
}

}

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

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

我能做什么?

最佳答案

你不能以这种方式从脚本引擎中的 StdErr 和 StdOut 读取,因为没有代码大师 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 """)

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

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

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

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

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

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

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

关于stdout - 使用 Windows 脚本宿主从 WshShell.Exec 捕获输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2075886/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com