cmd.exe是否写入stdout / stderr?

时间:2019-02-25 15:42:09

标签: windows cmd vbscript stdout command-prompt

这是一个奇怪的问题,基于我正在尝试解决的不良VBScript行为。请多多包涵,并先谢谢您。

在VBScript中,您可以执行以下操作来启动任务:

Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)
Do While WshShellExec.Status <> WshFinished
    WScript.Sleep(1000)
Loop

但是,存在一个错误,如果WshShell.Exec调用启动的命令/任务向StdOut或StdErr写入> = 4kb,则WshShellExec.Status 从不等于WshFinished( 1)。我认为这是因为系统用于stdout / stderr的缓冲区中没有空间,所以一旦向stdout / stderr写入了足够的字节,启动的任务就会挂起。

根据正在运行的程序,您可以执行以下操作来解决该问题:

Set wshShellExec = WshShell.Exec(cmd)
Set objStdOut = wshShellExec.StdOut
Set objStdErr = wshShellExec.StdErr

Do Until objStdOut.AtEndOfStream
    standardout = standardout & objStdOut.ReadLine & vbCrlf
Loop

Do Until objStdErr.AtEndOfStream
    errtext = errtext & objStdErr.ReadLine & vbCrlf
Loop

但是,这并不总是有效。如果正在运行的程序在将任何内容写入stdout之前将4kb写入stderr,则此代码将挂在objStdOut.AtEndOfStream或objStdOut.ReadLine的求值上(请注意,您不能使用objStdOut.ReadAll,因为这也会永远阻塞)。

因此,我想出了以下可行的解决方案:

strCommand = "c:\Windows\System32\cmd.exe /C StdOutTester.exe > " & rsltTextFile & " 2>&1 || call echo %^errorLevel% > " & rsltErrCodeFile

Set WshShellExec = WshShell.Exec(strCommand)

Do While WshShellExec.Status <> WshFinished 
    Wscript.Sleep(1000)
    secCount = secCount+1
    If secCount >= 10 Then 'kill children
        If KillTaskChildren(WshShellExec.ProcessID) <> 0 Then
            WScript.Echo "WMI Terminate Failed. Killing CMD..."
            WshShellExec.Terminate
        End If
    End If
Loop

这是在另一个cmd窗口中运行实际任务,然后将stdout / stderr重定向到文件(如果适用,还重定向错误代码)。因为我在另一个cmd窗口中运行命令,所以stdout和stderr与WshShellExec对象分离了。这也使我可以终止正在运行的任务以保持超时(通过使用WMI,它是真正的任务,即不是cmd窗口,而是实际任务)。

所以,我的问题变成了:

由于我正在运行另一个cmd.exe窗口,如果cmd提示符将足够的数据写入stdout / stderr(在这种情况下,我的超时逻辑应将其杀死),则cmd提示符本身可能也会遇到相同的问题?它实际上是否将任何内容写入stdout / stderr?如果我使用/ Q选项怎么办?

0 个答案:

没有答案