同时捕获和显示 STDOUT

Posted

技术标签:

【中文标题】同时捕获和显示 STDOUT【英文标题】:Capture and display STDOUT at the same time 【发布时间】:2013-05-04 01:14:23 【问题描述】:

我有以下代码来捕获和处理运行命令输出。 如何修改它以使运行命令窗口显示输出并同时记录输出?将 @SW_HIDE 替换为 @SW_SHOW(或等效项)只会显示一个空白命令窗口。

类似于 linux tee 命令的东西,它在打印 STDOUT 时记录到文件。

$CurrentPID = Run(@ComSpec & ' /c ' & $CurrentLogCmd, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD)

If Not ProcessWaitClose($CurrentPID,60) Then
    WriteLog("[Warning] Timed-out.Finding date in current hour raw log -" & $CurrentLogFileName)
    $F_LogWarningExist = 1
    Return $C_SUCCESS ; Take chances and proceed with parsing raw logs
EndIf

$CurrentOutput = StdoutRead($CurrentPID)

【问题讨论】:

【参考方案1】:
ConsoleWrite(_getDOSOutput('ipconfig /all') & @CRLF)

Func _getDOSOutput($command)
    Local $text = '', $Pid = Run('"' & @ComSpec & '" /c ' & $command, '', @SW_HIDE, 2 + 4)
    While 1
            $text &= StdoutRead($Pid, False, False)
            If @error Then ExitLoop
            Sleep(10)
    WEnd
    Return StringStripWS($text, 7)
EndFunc   ;==>_getDOSOutput

也许这可以帮助你。

【讨论】:

除了重定向之外,我实际上需要在窗口上打印文本...可以同时进行吗? 你这是什么意思? 我希望将文本打印在屏幕上以及重定向,以便 autoit 可以读取和解析。基本上,当我在监视器上时,我想立即查看发生了什么(脚本进度),而不是在最后等待 autoit 抛出错误(如果有的话)!【参考方案2】:

类似于 linux tee 命令的东西,它在打印 STDOUT 时记录到文件。

Redirecting STDOUT 让接收方(脚本)负责显示和记录。根据documentation:

StdoutRead() 不会阻塞,它会立即返回。为了获取所有数据,必须循环调用。

例子:

#AutoIt3Wrapper_Change2CUI=Y

#include <Constants.au3>
#include <MsgBoxConstants.au3>

Global Enum  $EXIT_OK, _
             $EXIT_NOCOMPILE, _
             $EXIT_ABORT

Global Const $g_sPromptError  = 'Compile this script and run resulting executable instead.', _
             $g_sPromptInput  = 'Enter a command:', _
             $g_sInputDefault = 'ping localhost -n 10'

Global       $g_sCMD = '', _
             $g_sSTD = ''

Main()

Func Main()

    If Not @Compiled Then

        MsgBox($MB_OK + $MB_ICONERROR, @ScriptName, $g_sPromptError)
        Exit $EXIT_NOCOMPILE

    EndIf

    $g_sCMD = InputBox(@ScriptName, $g_sPromptInput, $g_sInputDefault)
    If @error Then Exit $EXIT_ABORT

    $g_sSTD = _getCmdStd($g_sCMD)
    MsgBox($MB_OK + $MB_ICONINFORMATION, $g_sCMD, $g_sSTD)

    Exit $EXIT_OK
EndFunc

Func _getCmdStd(Const $sCMD, Const $sDir = '', Const $iType = $STDERR_MERGED, Const $bShow = False, Const $iDelay = 100)
    Local       $sTMP = ''
    Local       $sSTD = ''
    Local       $sCOM = @ComSpec & ' /c ' & $sCMD
    Local Const $iWin = $bShow ? @SW_SHOW : @SW_HIDE
    Local Const $iPID = Run($sCOM, $sDir, $iWin, $iType)

    While True

        $sTMP = StdoutRead($iPID, False, False)

        If @error Then

            ExitLoop 1

        ElseIf $sTMP Then

            $sTMP  = StringReplace($sTMP, @CR & @CR, '')
            $sSTD &= $sTMP

            ConsoleWrite($sTMP)

        EndIf

        Sleep($iDelay)

    WEnd

    Return SetError(@error, @extended, $sSTD)
EndFunc

执行完成后返回 STDOUT(和 STDERR),同时写入控制台执行期间。根据需要替换MsgBox()(记录功能)。

【讨论】:

以上是关于同时捕获和显示 STDOUT的主要内容,如果未能解决你的问题,请参考以下文章

在 Bash 中同时捕获标准输出和标准错误 [重复]

在 ARKit 中同时显示相机捕获图像和场景背景

使用多个 CALayers 捕获 UIVIew 的屏幕截图显示白色背景,同时将图像保存在图库中

捕获程序 stdout 和 stderr 以分隔变量

sh 卷曲并捕获stdout和http状态

sh 简单的gstreamer管道,用于将从网络摄像头捕获的视频录制到OGG,同时在屏幕上显示视频。