VBScript - 捕获stdout输出

3
我知道这个问题在另一个问题中已经得到了回答,但是我根本不明白该如何操作。
我试图将命令行程序(Aria2下载器)的输出结果放入HTA脚本中,以便可以动态地解析下载百分比、文件大小等内容,并将其更新到DIV中。
以下是我调整过并一直在尝试使用的代码,但它只会在命令行完成之前锁定界面,然后显示所有的输出结果,而不是实时地显示它们。
Const WshRunning = 0
Const WshFinished = 1
Const WshFailed = 2
strCommand = "ping.exe 127.0.0.1"

Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)

Do While WshShellExec.Status = WshRunning
    window.setTimeOut "", 100
Loop

Select Case WshShellExec.Status
    Case WshFinished
        strOutput = WshShellExec.StdOut.ReadAll()
    Case WshFailed
        strOutput = WshShellExec.StdErr.ReadAll()
End Select

Set objItem = Document.GetElementByID("status")
    objItem.InnerHTML = "" & strOutput & ""

如何修改代码以避免锁定用户界面,并在输出流传入时将其捕获并显示在“状态”div中?

“Const WshFailed = 2” 的基础是什么?MS文档中没有提供这样的状态码。https://msdn.microsoft.com/en-us/subscriptions/443b45a5(v=vs.84).aspx - ChrisJJ
1个回答

3
问题在于您的代码没有结束,也没有将控制权交还给浏览器。直到程序结束,循环才会停止,所以用户的感受是界面一直卡住直到子进程结束。
您需要设置一个回调函数,这样浏览器会定期调用您的代码,您就可以更新状态并结束循环。
<html>
<head>
    <title>pingTest</title>
    <HTA:APPLICATION
        APPLICATIONNAME="pingTest"
        ID="pingTest"
        VERSION="1.0"
    />
</head>

<script language="VBScript">
    Const WshRunning = 0
    Const WshFinished = 1
    Const WshFailed = 2

    Dim WshShellExec, Interval

    Sub Window_onLoad
        LaunchProcess
    End Sub

    Sub LaunchProcess
        Set WshShellExec = CreateObject("WScript.Shell").Exec("ping -n 10 127.0.0.1")
        Interval = window.setInterval(GetRef("UpdateStatus"),500)
    End Sub    

    Sub UpdateStatus
    Dim status 
        Set status = Document.GetElementByID("status")
        Select Case WshShellExec.Status
            Case WshRunning
                status.InnerHTML = status.InnerHTML & "<br>" & WshShellExec.StdOut.ReadLine()
            Case WshFinished, WshFailed
                status.InnerHTML = status.InnerHTML & "<br>" & Replace(WshShellExec.StdOut.ReadAll(),vbCRLF,"<br>")
                window.clearInterval(Interval)
                Interval = Empty
        End Select
    End Sub
</script>

<body>
    <div id="status"></div>
</body>
</html>

非常感谢,现在我明白了这个概念,你表达得非常清晰,谢谢。为什么WshRunning这行代码是这样写的:status.InnerHTML = status.InnerHTML & "<br>" & WshShellExec.StdOut.ReadLine()难道这不会像status.InnerHTML = WshShellExec.StdOut.ReadLine() 那样工作吗? - Ctrlaltdenied
1
@Ctrlaltdenied,我试图在读取命令时保留所有输出。每次使用ReadLine只能检索一行,因此为了保留所有输出,新行将附加到现有信息的末尾。当然,您评论中的代码可以工作,但不会显示相同的信息。对于每一行,您都会丢弃先前检索的信息并用新行替换它。 - MC ND
好的,这段代码的主要目的是启动一个下载任务,而Aria2在http/s、bittorrent等方面非常出色。我想扩展这个功能,将整个日志写入log.txt文件,同时保留输出中的关键元素以显示在页面上,例如下载信息(已下载量/总下载量、速度、百分比等)。再次感谢您的帮助。 - Ctrlaltdenied
哦,最后一个问题,这个示例中的命令是ping -n 10 127.0.0.1,除了 " 之外还有任何字符或符号是不被接受的吗?如果我需要输入包含 " 的命令作为字符串的一部分,我需要在这里做出特殊处理吗? - Ctrlaltdenied
1
@Ctrlaltdenied,如果您正在直接调用aria可执行文件,则不应该有任何问题字符,除了0x00(空字符)。引号是允许的,但要将它们包含在vbs字符串中,您需要将它们加倍,这只是vbs语法转义引号的方式。 - MC ND
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接