powershell - Powershell-输入标准输入后,捕获标准输出/标准错误不再起作用

标签 powershell process stdout stderr plink

在一个非常受限的环境中,如果我想自动化一些任务,基本上只允许使用Powershell + Plink。

我想创建一个函数:

  • 在需要时显示输出信息
  • 捕获所有输出(stdout和stderr),以使其稍后可用于进一步解析或记录到控制台/文件/无论
  • 自动输入密码

  • 不幸的是,在我输入密码的行之后,捕获输出停止了。当我只捕获标准输出时,它就可以工作了。在捕获了stderr之后,就再也没有运气了。

    编码:
    function BaseRun {
        param ($command, $arguments, $output = "Console")
    
        $procInfo = New-Object System.Diagnostics.ProcessStartInfo
        $procInfo.RedirectStandardOutput = $true
        $procInfo.RedirectStandardError = $true
        $procInfo.RedirectStandardInput = $true
        $procInfo.FileName = $command
        $procInfo.Arguments = $arguments
        $procInfo.UseShellExecute = $false
    
        $process = New-Object System.Diagnostics.Process
        $process.StartInfo = $procInfo
        [void]$process.Start()
    
        $outputStream = $process.StandardOutput
        $errorStream = $process.StandardError
        $inputStream = $process.StandardInput
    
        $outputBuffer = New-Object System.Text.StringBuilder
    
        Start-Sleep -m 2000
        $inputStream.Write("${env:password}`n")
    
        while (-not $process.HasExited) {
            do {
                $outputLine = $outputStream.ReadLine()
                $errorLine = $errorStream.ReadLine()
                [void]$outputBuffer.Append("$outputLine`n")
    
                if (($output -eq "All") -or ($output -eq "Console")) {
                    Write-Host "$outputLine"
                    Write-Host "$errorLine"
                }
            } while (($outputLine -ne $null) -and ($errorLine -ne $null))
        }
    
        return $outputBuffer.ToString()
    }
    

    最佳答案

    基于@ w0xx0m和@Martin Prikryl的帮助,我设法制定了这个可行的解决方案:

    Register-ObjectEvent -InputObject $process `
        -EventName OutputDataReceived -SourceIdentifier processOutputDataReceived `
        -Action {
        $data = $EventArgs.data
        if($data -ne $null) { Write-Host $data }
    } | Out-Null
    
    Register-ObjectEvent -InputObject $process `
        -EventName ErrorDataReceived -SourceIdentifier processErrorDataReceived `
        -Action {
        $data = $EventArgs.data
        if($data -ne $null) { Write-Host $data }
    } | Out-Null
    
    [void]$process.Start()
    $process.BeginOutputReadLine()
    $process.BeginErrorReadLine()
    
    $inputStream = $process.StandardInput
    
    Start-Sleep -m 2000
    $inputStream.Write("${env:password}`n")
    
    $process.WaitForExit()
    
    Unregister-Event -SourceIdentifier processOutputDataReceived
    Unregister-Event -SourceIdentifier processErrorDataReceived
    
    $inputStream.Close()    
    

    为简便起见,我删除了进程启动部分(与上面的部分相同)和数据处理(在示例中,我只是对其进行写托管)。

    关于powershell - Powershell-输入标准输入后,捕获标准输出/标准错误不再起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42536822/

    相关文章:

    python运行2个进程

    linux - 在ubuntu中检查进程的启动时间后,有没有办法在一定时间后杀死进程?

    c++ - 我如何为我的应用程序创建自己的实例 excel 并使用它?

    ios - 在 Objective C 中捕获标准输出

    linux - 在 AT&T 汇编中使用 stdin 和 stdout 连续读写

    带有值表达式的 Powershell Add-Member

    arrays - 在没有 “@{”的情况下获取单个属性

    linux - 使用 C/C++ 应用程序持续监控 linux 控制台日志

    javascript - 内容未定义,错误为错误 :ENOENT, 打开 'C:\Windows\system32\hello.txt'

    Powershell 在 If 语句中尝试使用 -and 时出错