除非指定了输出文件,否则VBScript的Shell命令将不会执行

时间:2019-02-01 03:37:09

标签: cmd vbscript command-prompt

我正在尝试运行Shell命令进行Google语音识别。如果我将输出文件提供给命令字符串,则只能运行命令

您可以在下面看到我的测试代码示例,如果提供了该代码,我将附加“> outputFile ”,并在超时循环中进行编码,以在设置的时间限制后中止该过程。

strCommand = "cmd /c ipconfig /all"
If outputFile <> "" Then
    strCommand = strCommand & " > """ & outputFile & """"
End If
Set wshShellExec = wshShell.Exec(strCommand)
expiration = DateAdd("s", 600, Now)
Do While wshShellExec.Status = WshRunning And Now < expiration
    WScript.Sleep 5000
Loop 
Select Case wshShellExec.Status
    Case WshRunning
        wshShellExec.Terminate
        TestFunction = "{""error"": ""TestFunction Command Timed Out""}"
    Case WshFinished
        TestFunction =  WshShellExec.StdOut.ReadAll()
    Case WshFailed
        TestFunction = wshShellExec.StdErr.ReadAll()
End Select

如果我将outputFile保留为空,并希望从该函数返回输出,则它所要做的只是静止5分钟,然后超时并向我发送错误消息。 为什么需要输出文件才能运行? 如果我在命令提示符上手动运行命令行,它将运行得很好。

2 个答案:

答案 0 :(得分:0)

一旦wshShellExecWshRunning情况下终止,则应该分配输出,而不是分配错误消息。

Select Case wshShellExec.Status
Case WshRunning
    wshShellExec.Terminate
    TestFunction = "Terminated: " & vbcrlf & WshShellExec.StdOut.ReadAll() 
Case WshFinished
    TestFunction =  "Finished: " & vbcrlf & WshShellExec.StdOut.ReadAll()
Case WshFailed
    TestFunction = wshShellExec.StdErr.ReadAll()
End Select

答案 1 :(得分:0)

输出缓冲区的容量有限。如果您的命令写了太多文本无法输出,缓冲区将填满并阻止该命令继续写命令,直到您清除缓冲区为止(例如,通过读取缓冲区)。 ReadAll不能用于此目的,因为该方法仅在命令完成后返回 ,否则将阻塞,从而造成死锁。

您最好的选择是将输出重定向到一个或多个(临时)文件,并在命令完成后从这些文件中读取输出。

outfile = "C:\out.txt"
errfile = "C:\err.txt"

cmd = "cmd /c ipconfig /all >""" & outfile & """ 2>""" & errfile & """"

timeout = DateAdd("s", 600, Now)

Set sh = CreateObject("WScript.Shell")
Set ex = sh.Exec(cmd)
Do While ex.Status = WshRunning And Now < timeout
    WScript.Sleep 200
Loop

Set fso = CreateObject("Scripting.FileSystemObject")
outtxt = fso.OpenTextFile(outfile).ReadAll
errtxt = fso.OpenTextFile(errfile).ReadAll

如果由于某些原因您不想这样做,则必须反复阅读StdOut

outtxt = ""
errtxt = ""

cmd = "ipconfig /all"

timeout = DateAdd("s", 600, Now)

Set sh = CreateObject("WScript.Shell")
Set ex = sh.Exec(cmd)
Do While ex.Status = WshRunning And Now < timeout
    WScript.Sleep 200
    outtxt = outtxt & ex.StdOut.ReadLine & vbNewLine
Loop

请注意,您可能还需要从StdErr中读取内容,因为如果错误输出过多,该缓冲区也可能会填满。但是,读取两个缓冲区都可能导致另一个死锁,因为IIRC ReadLine会阻塞直到可以读取整行为止,因此如果脚本可能挂起以等待错误输出永远不会出现。您也许可以使用Read而不是ReadLine来解决此问题,但它仍然非常脆弱。

因此,再次,您最好的选择是将命令输出重定向到文件,并在命令终止后读取这些文件。