异步重定向StandardOutput和StandardError
本文关键字:StandardError StandardOutput 重定向 异步 | 更新日期: 2023-09-27 18:12:41
我试图重定向一个长过程的标准输出和标准错误。这是一个可能需要40分钟才能完成处理的Exe文件。
问题是,如果我从命令行(cmd)运行EXE, stdout和stderr以某种顺序显示在控制台上,这是我希望它从我的应用程序重定向的顺序,但它不起作用。我在使用以下函数的时候改变了顺序,找不到原因是什么。我希望你能给我一些建议。
这是我使用的代码:
Public numOutputLines As Integer = 0
Public sortOutput As StringBuilder = Nothing
Public Function ProcessTask3New(ByVal ExeName As String, ByVal arguments As String, ByRef stdout As String, ByRef stderr As String, ByRef ExitCode As Integer, _
Optional ByVal Filename As String = "", Optional ByVal IsDeleteTempLogFiles As Boolean = False) As Boolean
' This fucntion executes cmd commands and arguments,
' Function returns standard output and startdard error. stderr contains data if error was generated
Try
ProcessTask3New = True
Dim p As Process
Dim psi As ProcessStartInfo
Dim currentTime As System.DateTime
currentTime = System.DateTime.Now
If Filename <> "" Then Filename = Replace(Filename & ".", "'", "")
Dim tmpStdoutFilename As String = System.IO.Path.GetTempPath & "stdout." & Filename & currentTime.Ticks.ToString()
Dim tmpStderrFilename As String = System.IO.Path.GetTempPath & "stderr." & Filename & currentTime.Ticks.ToString()
netOutput = New StringBuilder
p = New Process
psi = p.StartInfo
psi.Arguments = psi.Arguments.Replace("/C " & Chr(34), "/C " & Chr(34) & Chr(34))
psi.FileName = ExeName
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Minimized
' Redirect the standard output of the sort command.
' Read the stream asynchronously using an event handler.
psi.RedirectStandardOutput = True
psi.RedirectStandardError = True
psi.CreateNoWindow = True
sortOutput = New StringBuilder()
' Set our event handler to asynchronously read the sort output.
AddHandler p.OutputDataReceived, _
AddressOf SortOutputHandler
AddHandler p.ErrorDataReceived, AddressOf SortOutputHandler
If IsDebug Then Write2Log("ProcessTask3New: " + psi.FileName.ToString + " " + psi.Arguments.ToString)
Try
Write2Log(My.Computer.FileSystem.CurrentDirectory)
p.Start()
Catch w As System.ComponentModel.Win32Exception
Write2Log("ProcessTask3New: " & w.Message)
Write2Log("ProcessTask3New: " & w.ErrorCode.ToString())
Write2Log("ProcessTask3New: " & w.NativeErrorCode.ToString())
Write2Log("ProcessTask3New: " & w.StackTrace)
Write2Log("ProcessTask3New: " & w.Source)
Dim e As New Exception()
e = w.GetBaseException()
Write2Log("ProcessTask3New: " & e.Message)
End Try
' Start the asynchronous read of the sort output stream.
p.BeginOutputReadLine()
p.BeginErrorReadLine()
p.WaitForExit()
ExitCode = p.ExitCode
p.Close()
netOutput = Nothing
Catch ex As Exception
Write2Log("error at ProcessTask3New function: " & ex.ToString & " : " + ex.StackTrace)
End Try
End Function
Private Sub SortOutputHandler(ByVal sendingProcess As Object, _
ByVal outLine As DataReceivedEventArgs)
' Collect the sort command output.
If Not String.IsNullOrEmpty(outLine.Data) Then
numOutputLines += 1
Add the text to the collected output.
sortOutput.Append(Environment.NewLine + "[" _
+ numOutputLines.ToString() + "] - " _
+ outLine.Data)
End If
End Sub
现在输出这是我从cmd窗口运行它时的样子(这很好):
处理密钥文件:vob_db.k01(1),共291个节点
处理删除链:删除链上有1个节点。处理节点:+ + + + + + + + + 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60 %+++++++++ 70年 %+++++++++ 80年 %+++++++++ 90年 %+++++++++
100%处理密钥文件:vob_db.k02(2),共1246个节点
处理删除链:删除链上有2个节点。处理节点:+ + + + + + + + + 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60 %+++++++++ 70年 %+++++++++ 80年 %+++++++++ 90年 %+++++++++
100%处理密钥文件:vob_db.k03(5),共1个节点
处理删除链:删除链上有0个节点。处理节点:
100%处理密钥文件:vob_db.k04(6),共277个节点
处理删除链:删除链上有7个节点。处理节点:+ + + + + + + + + 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60 %+++++++++ 70年 %+++++++++ 80年 %+++++++++ 90年 %+++++++++
100%
(像这样的行来自stderr.)
+++++++++ 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60% + +
当我从我的应用程序中运行它时(这是坏的):
ProcessTask3New: cmd.exe/C "C:'Program Files . C(x86)…"-a -k -R -r1-p29000 vob_db" E:'backup2'db db_VISTA Version 3.20数据库一致性检查实用程序版权所有(C) 1985-1990 Raima公司版权所有------------------------------------------------------------------------ 处理密钥文件:vob_db.k01(1),共有291个节点------------------------------------------------------------------------ 处理密钥文件:vob_db.k02(2),共有1246个节点------------------------------------------------------------------------ 处理密钥文件:vob_db.k03(5), 1个节点------------------------------------------------------------------------ 处理密钥文件:vob_db.k04(6),共有277个节点------------------------------------------------------------------------ 处理数据文件:vob_db.d01(0),共有7107条记录------------------------------------------------------------------------ 处理数据文件:vob_db.d02(3),共有20516条记录------------------------------------------------------------------------ 处理数据文件:vob_db.d03(4),共记录------------------------------------------------------------------------ 处理数据文件:vob_db.d04(7),共0记录------------------------------------------------------------------------ 处理数据文件:vob_db.d05(8),总共39938条记录处理删除链:删除链上有1个节点。在0中遇到0个错误记录/节点+ + + + + + + + + 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60 %+++++++++ 70年 %+++++++++ 80年 %+++++++++ 90年 %+++++++++ 100%处理删除链:2节点删除链。处理节点:+ + + + + + + + + 10 %+++++++++ 20 %+++++++++ 30 %+++++++++ 40 %+++++++++ 50 %+++++++++ 60 %+++++++++ 70年 %+++++++++ 80年 %+++++++++ 90年 %+++++++++ 100%处理删除链:0节点删除链。处理节点:
100%
请建议。谢谢你!
您可以选择"混合"标准输出和标准错误,将标准错误重定向到标准输出
cmd /c "commandToRun 2>&1"
这里我们要求cmd
执行一些命令并将流2 (stderr)的输出重定向到流1 (stdout)。
不同顺序背后的原因是,当在控制台时,单个输出流确实被分配给"标准输出"answers"错误输出",并且当您的应用程序调用时,有两个不同步的流,因此您的SortOutputHandler
事件以任何顺序调用(如果在写入输出或刷新之间有极长的暂停,它可能会得到正确的顺序)。
唯一的解决方案,你必须得到这个很好的排序是确保有一个单一的流。问题是,我不知道一个解决方案允许使用ProcessStartInfo类。一种可能性是以"暂停"模式启动进程,然后强制将其标准错误句柄重定向到输出句柄,然后让它运行(如cmd.exe
所做的)