异步重定向StandardOutput和StandardError

时间:2014-07-11 13:03:48

标签: c# .net vb.net windows cmd

我试图重定向长时间进程的stdout和stderr。它可能需要40分钟才能完成处理。

问题是如果我从命令行(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&#34;&#34; C:\ Program Files   (86)..&#34; -a -k -R -r1   -p29000 vob_db&#34; E:\ backup2 \ db db_VISTA版本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),共1条记录   -------------------------------------------------- ----------------------处理数据文件:vob_db.d04(7),共0条记录   -------------------------------------------------- ----------------------处理数据文件:vob_db.d05(8),共处理39938条记录   删除链:删除链上的1个节点。 0遇到0错误   记录/节点   +++++++++ 10%+++++++++ 20%+++++++++ 30%+++++++++ 40%++++++ +++ 50%+++++++++ 60%+++++++++ 70%+++++++++ 80%+++++++++ 90%+ ++++++++++++++++++++++++++++++++++++++处理节点:   +++++++++ 10%+++++++++ 20%+++++++++ 30%+++++++++ 40%++++++ +++ 50%+++++++++ 60%+++++++++ 70%+++++++++ 80%+++++++++ 90%+ +++++++++++++++++++++++++++++++++++++++处理节点:   100%

请指教。谢谢!

2 个答案:

答案 0 :(得分:2)

您可以选择&#34;混合&#34; stdout和stderr,将stderr重定向到stdout

cmd /c "commandToRun 2>&1"

这里我们要求cmd执行一些命令并重定向流2(stderr)将其输出发送到流1(stdout)。

但是,显然你不会在stderr上检索任何数据。

答案 1 :(得分:0)

不同命令背后的原因是,在控制台中,单个输出流确实分配给“标准输出”和“错误输出”,并且当您的应用程序调用时,有两个流不同步,因此您的SortOutputHandler事件以任何顺序被调用(如果在输出或刷新之间有非常长的暂停,它可能会被正确地命令)。

您必须对此进行良好排序的唯一解决方案是确保存在单个流。问题是我不知道允许使用ProcessStartInfo类的解决方案。 一种可能性是以“暂停”模式启动进程,然后将其标准错误句柄强制重定向到输出句柄,然后让它运行(如cmd.exe那样)