View Full Version : (VB.NET) redirecting STDOUT line by line in real time and sending to another window
OvejaNegra
9th December 2010, 18:45
I'm trying to capture the stdout (and if possible, stderr) of one aplication (FLAC.EXE and LAME and others on the future).
I'm trying to do it line by line in real time (reading a line as the aplication outputs something new on the console).
My goal is use that information to display a progress window (like megui + x264).
But it does not works (it does not outputs anything)
Im using a code like this one (but with flac offcourse):
Dim myprocess As Process = New Process
myprocess.StartInfo.FileName = "ping"
myprocess.StartInfo.Arguments = TextBox2.Text
myprocess.StartInfo.UseShellExecute = False
myprocess.StartInfo.CreateNoWindow = True
myprocess.StartInfo.RedirectStandardInput = True
myprocess.StartInfo.RedirectStandardOutput = True
myprocess.StartInfo.RedirectStandardError = True
myprocess.Start()
While (myprocess.HasExited = False)
Dim sLine As String = myprocess.StandardOutput.ReadLine
If (Not String.IsNullOrEmpty(sLine)) Then
End If
Me.TextBox1.Text &= sLine & vbCrLf
Application.DoEvents()
End While
Me.TextBox1.Text += "Completed"
with ping, it works (it captures each line separately)
but with flac, it does not.
Also, while ping is working,the window with the textbox is freezed (until ping ends).
what can i do to avoid that?
thanks
The Scientist
9th December 2010, 20:14
Show the code that doesn't work, not the code that does.
Selur
9th December 2010, 20:28
Also, while ping is working,the window with the textbox is freezed (until ping ends).
no clue about, VB.NET but this happens because you are not starting your while-statement in a different thread and so causing the whole program (with the ui in it ;)) to wait. :P
what can i do to avoid that?
maybe this helps: http://www.vb-helper.com/howto_net_run_threads.html
OvejaNegra
9th December 2010, 23:21
Scientist: well, that code does not works with FLAC
i'm going to start with the thread stuff right now, thanks
Gavino
11th December 2010, 00:00
no clue about, VB.NET but this happens because you are not starting your while-statement in a different thread and so causing the whole program (with the ui in it ;)) to wait. :P
I've no real clue about VB.NET either, but doesn't the call to Application.DoEvents take care of that aspect?
EDIT: Probably not, if Readline is a blocking call.
Still doesn't explain the difference between ping and flac, though.
OvejaNegra
11th December 2010, 07:25
i'm goint to test all the segestions tomorrow, but (ok its wierd)
Using flac.exe --explain works like a charm (it captures all the help), but using normal encoding commands, does not works.
maybe bacause flac outputs always on the same line? (--explain outputs the help using differents lines for every sentence)
thanks
Gavino
11th December 2010, 10:14
Using flac.exe --explain works like a charm (it captures all the help), but using normal encoding commands, does not works.
maybe bacause flac outputs always on the same line? (--explain outputs the help using differents lines for every sentence)
Even if it outputs a single line, I would expect to get the output when it finishes - instead, you say you get nothing at all.
Perhaps the text output is sent to stderr when encoding, since stdout may be used for the encoded output (depending on options used).
Incidentally I think there is an error in your code:
If (Not String.IsNullOrEmpty(sLine)) Then
End If
Me.TextBox1.Text &= sLine & vbCrLf
The last line should come before the End If. However, I don't think this is the reason for your problem.
LoRd_MuldeR
11th December 2010, 12:34
OvejaNegra, are you sure you don't get any output at all when capturing both, stdout and stderr?
Quite often you will notice that the authors of CLI tools just forgot to call fflush() after printf()-ing their status updates, so the updates won't be flushed immediately.
In the console you won't notice that for some reason, but when piping the output to another process you will!
As a result you don't get the status updates continuously, as desired. Instead you receive a "burst" every now and then (when the buffer ran full and flushed itself).
It can even happen that you don't receive anything, until process terminates. There is no way to fix that (to my knowledge) on your side...
[EDIT]
Another thought: I'm not familiar with VB.Net, but you use ReadLine(), which might block (i.e. not return) until a line-break ("\n") character is encountered.
But when printing out status update one usually avoids such line-breaks. Instead we just "print" a bunch of backspace characters ("\b") before the next status update.
So if the VB.Net process API allows, try using something like ReadAll() instead of ReadLine().
You of course must be prepared to receive a long string like "1% done.\b\b\b\b\b2% done.\b\b\b\b\b3% done.\b\b\b\b\b4% done.\b\b\b\b\b...." then ;)
Here is how I currently do it in C++/Qt, just as an example:
http://pastie.org/private/0itb9yn5maskzkrzhwm6a
In this example only the waitForReadyRead() blocks, but it doesn't wait for a "\n" character. Also note that the readLine() function here does NOT block.
It just reads everything until either a "\n" character is encountered or the end of the stream is reached. Either way, it returns immediately!
The Scientist
11th December 2010, 15:04
OK so I've had a little mess with "flac.exe" and 'kind of' got it to work. It definitely outputs its progress to stderr so your original method used in post #1 wouldn't have worked, but that aside, I whipped up a small app and got 'flac.exe' converting a WAV file to FLAC whilst receiving progress.
But...... although the method works for most other programs the progress returned in 'flac.exe' is sporadic, not a nice 1% to 100%, it is doing it in bursts, workable but not ideal so I think "LoRd_MuldeR" has hit the nail on the head when he said:
Quite often you will notice that the authors of CLI tools just forgot to call fflush() after printf()-ing their status updates, so the updates won't be flushed immediately. In the console you won't notice that for some reason, but when piping the output to another process you will!
As a result you don't get the status updates continuously, as desired. Instead you receive a "burst" every now and then (when the buffer ran full and flushed itself).
LoRd_MuldeR
11th December 2010, 15:35
OK so I've had a little mess with "flac.exe" and 'kind of' got it to work. It definitely outputs its progress to stderr so your original method used in post #1 wouldn't have worked, but that aside, I whipped up a small app and got 'flac.exe' converting a WAV file to FLAC whilst receiving progress.
But...... although the method works for most other programs the progress returned in 'flac.exe' is sporadic, not a nice 1% to 100%, it is doing it in bursts, workable but not ideal so I think "LoRd_MuldeR" has hit the nail on the head when he said:
Fortunately this is easy to fix, only inside FLAC itself though.
Just compile FLAC from the sources yourself, search for the fprintf(stderr, "%d%% done", x) and put a simple fflush(stderr) right after that line :)
That's what I have done with OggDec, FAAD and others. Quite often you'll also have to hack in support for Unicode filenames yourself :rolleyes:
OvejaNegra
13th December 2010, 05:46
sorry, it's late and i cant give details now, but LoRd_MuldeR you are right.
i have the source of flac and i have c++express, i will compile the code with the fixes you suggest and i will post results
thanks to all of you.
OvejaNegra
22nd December 2010, 18:47
Hi!
Just a small post telling that after compiling the flac source with the suggestions from LoRd_MuldeR IS OK and i have output (from stderr) with the progress of flac line by line.
Also, i implemented the output capture in another thread, so no more freezing on the UI. thanks to everyone for the advices!
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.