0

Imagine that from my application I launch a Commandline application that prints on the standard output this line:

I'm a standard line with special character: #

And after that, the same application prints this line in the error output:

I'm an error line with special character: @

So the CMD output is exactly this regardless of whether the kind of output:

I'm a standard line with special character: #
I'm an error line with special character: @

Then, regardless of whether it is the standard or error output, How I could read both lines at the same time? (the full CMD output) , or in other words, how to read the console buffer?

CLARIFICATION:

I don't mean how to redirect a process output to read the standard input, or the error output, or both, I already know how to do that, what I mean is to read the console buffer, a buffer where (I think) all outputs (Standard/Error/Input) are merged as only one output in the stream with no needing to redirect the desired output, just reading the buffer stream I could search for a special character printed by the application, regardless the kind of output which printed the special character.

To understand it better, this is a pseudo-code:

Private Sub ReadConsoleBuffer()

    Dim p As New Process With
    {.StartInfo = New ProcessStartInfo With
                  {.FileName = "MyApp.exe",
                   .UseShellExecute = False,
                   .RedirectStandardError = False,
                   .RedirectStandardOutput = False}} ' There is no need to redirect output because I'm not trying to capture the outputs by myself.

    p.Start()

    ' Process will write an "#" character on the Standard Output,
    ' And will write an "@" character on the Error Output.

    Dim cBuffer As IO.StreamReader = ' ...Function to retrieve the console buffer...

    Do Until cBuffer.EndOfStream

        Select Case Convert.ToChar(cBuffer.Read)

            Case "#"
                ' "#" character found so we succesfully read the Standard Output from the buffer.
            Case "@"
                ' "@" character found so we succesfully read the Error Output from the buffer.
        End Select

        cBuffer = ' ...Reassign the buffer data to retrieve new printed lines by the process?... 
        ' really I'm not sure that this would be necessary or not.

    Loop

End Sub

I hope that you could notice right the difference between what I would like to do, and what I don't would like to do, the code above is what I would like to do, and this else example of a normally output redirection is what I don't would like to do:

Private Sub ReadConsoleBuffer() Handles MyBase.Shown

    Dim p As New Process With
    {.StartInfo = New ProcessStartInfo With
                  {.FileName = "cmd.exe",
                   .Arguments = "/C Dir /W *.ext not found",
                   .UseShellExecute = False,
                   .RedirectStandardError = True,
                   .RedirectStandardOutput = True}}

    p.Start()

    Do Until (p.StandardOutput.EndOfStream And p.StandardError.EndOfStream)
        RTB_stdOut.AppendText(p.StandardOutput.ReadLine & Environment.NewLine)
        RTB_errOut.AppendText(p.StandardError.ReadLine & Environment.NewLine)
    Loop

End Sub

PS: This question is the second part of these else uncleared questions:

Need an aclaration about the console buffer and console outputs

How to read Console buffer in VBNET?

I've already know how to do those things but seems that people couldn't understand my problem, I wonder that this time I've exposed a better explanation of my problem and what I'm trying to do.

Community
  • 1
  • 1
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417

1 Answers1

3

Well your question still seems hard to wrap around:

Why do you seperate stdout and stderr by using tokens in the output?

If you want to read the buffer of the stdout and stderr seperatly, just do it!

Create two StreamReaders, one initialized with StandardError, the other with StandardOutput, read them seperatly, store them seperatly and voila!

Since you insist you know how to do it, i'll leave you with one final counter question:

Why would you want to have access to the entire "console buffer" and sort stdout/stderr later by some special characters, if you already have access to the seperate streams of stdout and stderr?

Edit: After testing the processes in question i have one suggestion:

Do not use StreamReaders to receive data from your child process. Try following way:

Create two methods:

Private Sub hndStdOutDataReceiver(sender As Object, e As DataReceivedEventArgs)
        ' Here comes the content from StdOut, do with it what you please
        RTB_Output.AppendText(e.Data)
End Sub
Private Sub hndStdErrDataRecevier(sender As Object, e As DataReceivedEventArgs)
        ' Here comes the content from StdErr, do with it what you please
        RTB_Error.AppendText(e.Data)
End Sub

And when redirecting the StandardOutput/Error of the far process instead of creating StreamReaders that handle the readout use the Events: OutputDataReceived and ErrorDataReceived

Dim psi As ProcessStartInfo = New ProcessStartInfo
With psi
        .FileName = YOUR_FILENAME
        .Arguments = YOUR_ARGUMENTS
        .UseShellExecute = False
        .RedirectStandardOutput = True
        .RedirectStandardError = True
End With
Dim proc as New Process() With { .StartInfo = psi }

' Here comes the crucial difference to your method
AddHandler proc.OutputDataReceived, AddressOf hndStdOutDataReceiver
AddHandler proc.ErrorDataReceived, AddressOf hndStdErrDataRecevier

proc.Start()

proc.BeginOutputReadLine()
proc.BeginErrorReadLine()

proc.WaitForExit()

' wrap up your environment 
MrPaulch
  • 1,423
  • 17
  • 21
  • Answering to your question, unafortunally I need to launch some buggy applications, where, if I redirect the error output (in the same way like I've did in the example that I given) then the standard output is missed, is empty. And the same thing happens for the standard output, if I redirect the standard output of the buggy application then I could not read anything from the error output, That means what I only can read one of the outputs per run, and that's the reason why I would like to read the entire CMD output (console buffer) regardless the kind of output that I want to read. – ElektroStudios Nov 25 '13 at 13:34
  • That seems interesting, i don't think you can provide me with a copy of that buggy program? Have you tried to read the stderr and stdout in seperate threads? I suspect that eighter the process exits to early after you read one of the two streams or your way to read them is flawd. In the example provided, your Do loop uses the condition (p.StandardError.EndOfStream AndAlso p.StandardOutput.EndOfStream) which obviosly is false if eighter of the streams reaches it's end. subsequently the other has no chance to complete... – MrPaulch Nov 25 '13 at 13:41
  • The example that I given is just to show how to "merge them?", it is just a bad example don't give your attention to that code, as normally I separate the error/output streams in two objects to read them by separatelly line by line. I could ensure you that is not my fault, in other all applications I'm able to read both outputs, but one of the buggy process is an Audio converter, it takes like 5-10 mins to make a converter operation and exits, then I have a lot of time to be able to try to read from the output(s), but like I've said I'm not able to read from both outputs with that app. – ElektroStudios Nov 25 '13 at 13:49
  • One of the apps in question is dbPoweramp Converter http://www.dbpoweramp.com/install/dMC-R14.4-Ref-Trial.exe ("coreconverter.exe" inside is the CLI process). PS: Sorry for my bad English and thanks for your help. – ElektroStudios Nov 25 '13 at 13:50
  • Could you give an example as to how you execute the coreconverter.exe? What parameter, what type of files? – MrPaulch Nov 25 '13 at 13:52
  • Here you can download a "bugged output application" http://sourceforge.net/projects/mp3gain/files/MP3Gain-Windows%20%28Stable%29/1.2.5/mp3gain-win-1_2_5.zip/download and you can use this class that I've did to manage the application in VBNET http://pastebin.com/S6KYzk3f ,in the Variables region of the code you could see how I instace 2 different processes, the process named "Process_For_Tag" if I dont remember bad then If I enable both output redirections for that process then I'm not able to read anything from the standard output because anything is written there, thats why I create two procs – ElektroStudios Nov 25 '13 at 14:03
  • 1
    OK i tested both with an app of mine... that does the readout quiet differently.. i will update my post to inform you how – MrPaulch Nov 25 '13 at 14:09