这是一个奇怪的问题,基于我正在尝试解决的不良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选项怎么办?