469,626 Members | 1,512 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,626 developers. It's quick & easy.

Strange behavior of redirected stdout. Streams Broken?

Oz
This is long. Bear with me, as I will really go through all the convoluted
stuff that shows there is a problem with streams (at least when used to
redirect stdout).

The basic idea is that my application (VB.NET) will start a process,
redirect its stdout and capture that process' output, displaying it in a
window.

I've written a component for this, and a test application for the component.
It allows me to specify a command to execute, and also whether that command
is executed via a cmd.exe shell (like "dir"), or not (such as when directly
running a console application).

I then found a nearly identical solution in an article at
http://www.codeguru.com/Csharp/Cshar...cle.php/c8503/

That article contains pretty much what I also have done.

So here's the problem. It appears that there is something weird about
console applications that can make them hang or not output when run in this
way (through System.Diagnostics.Process).

Just to head off some questions, when I am reading my redirected stdout and
stderr, I always peek first, then read the character. Yes, char-at-a-time is
not terribly efficient, but it works for this purpose.

Note that to intercept stdout/stderr, you have to start the application with
no window (per docs on the Process object).

I have a particular console app that I'm capturing. This application, once
started, outputs lines as it progresses, and eventually completes. It takes
no user input -- it simply logs lines to stdout. Sounds simple.

Observations:

- Start cmd.exe and run this application; it works fine.

- My interceptor starts the application by starting cmd.exe (with no window)
and then having that process start the application by feeding its stdin with
the command line necessary to do so. In this case, it is cmd.exe which my
application is intercepting, and so I get whatever cmd.exe would output. I do
get the initial two lines introducing cmd.exe (with version and so forth),
and the prompt line, and I see the command to start the application after the
prompt. The application does start (as seen in task list), but no further
output is captured. Breakpoints verify that in fact nothing is being seen in
the stdout or stderr pipes at all. HOWEVER... this is only true when the
application is long-running (and so I eventually abort it). When I run it on
a very short test, which results in the application completing in a few
seconds, and producing only a few lines, then these lines ARE presented to
stdout and captured!

- The interceptor starts the application directly (not via cmd.exe). No
output is seen (but not attempted on the short-running case).

This all made me think that the output is buffered, and indeed it is
normally, per documentation of printf (and the target app is a C app). So I
decided I'd check this out by creating a very simple console app in VB.NET.

The simplest version is this one:
-----------------------

Sub Main()
Dim nLine As Integer

System.Console.WriteLine("RBAC console write test.")

For nLine = 1 To 20
System.Console.WriteLine(String.Format("Console write test --
line {0}.", nLine))
Next

System.Console.WriteLine("Done.")
End Sub
------------------------------

When I run this directly (not via cmd.exe), my interceptor gets the outputs
expected:
--------------
RBAC console write test.
Console write test -- line 1.
Console write test -- line 2.
Console write test -- line 3.
Console write test -- line 4.
Console write test -- line 5.
Console write test -- line 6.
Console write test -- line 7.
Console write test -- line 8.
Console write test -- line 9.
Console write test -- line 10.
Console write test -- line 11.
Console write test -- line 12.
Console write test -- line 13.
Console write test -- line 14.
Console write test -- line 15.
Console write test -- line 16.
Console write test -- line 17.
Console write test -- line 18.
Console write test -- line 19.
Console write test -- line 20.
Done.
----------------

and when run via cmd.exe:
-----------------
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\00sts\RBAC\NET\ConsoleAppTest\ConsoleAppTest\bi n>consoleAppTest.exe
-----------------

That is, the output doesn't appear when the interceptor starts cmd.exe and
feeds the command to it. As you can see, the command itself is fine. To
verify that commands can be intercepted, I execute "dir" in the same context,
via the interceptor:
--------------------
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\00sts\RBAC\NET\ConsoleAppTest\ConsoleAppTest\bi n>dir
Volume in drive C has no label.
Volume Serial Number is E8B4-4400

Directory of C:\00sts\RBAC\NET\ConsoleAppTest\ConsoleAppTest\bi n

07/21/2005 06:46 PM <DIR> .
07/21/2005 06:46 PM <DIR> ..
07/22/2005 12:34 PM 6,656 ConsoleAppTest.exe
07/22/2005 12:34 PM 11,776 ConsoleAppTest.pdb
2 File(s) 18,432 bytes
2 Dir(s) 9,501,356,032 bytes free

C:\00sts\RBAC\NET\ConsoleAppTest\ConsoleAppTest\bi n>exit
------------------------

This shows that in fact I should get whatever is displayed in the console.
So I then start up cmd.exe manually, and run the ConsoleAppTest.exe:

---------------------
C:\00sts\RBAC\NET\ConsoleAppTest\ConsoleAppTest\bi n>consoleapptest
RBAC console write test.
Console write test -- line 1.
Console write test -- line 2.
Console write test -- line 3.
Console write test -- line 4.
Console write test -- line 5.
Console write test -- line 6.
Console write test -- line 7.
Console write test -- line 8.
Console write test -- line 9.
Console write test -- line 10.
Console write test -- line 11.
Console write test -- line 12.
Console write test -- line 13.
Console write test -- line 14.
Console write test -- line 15.
Console write test -- line 16.
Console write test -- line 17.
Console write test -- line 18.
Console write test -- line 19.
Console write test -- line 20.
Done.
------------------------------

This just shows that normally in cmd.exe, I will get the output.

While most of this is background for what comes next, there is already the
inexplicable failure to find the lines of output when cmd.exe is started
through the Process class.

Below is the code for starting the process, whether using cmd.exe or not.
Not that "swOut" and "swErr" are StreamReader objects declared at the object
scope of the encapsulating class.

------------------
Dim swIn As StreamWriter
oProc = New Process

If bUseCmdExe Then
oProc.StartInfo.FileName = "cmd.exe"
Else
oProc.StartInfo.FileName = sRunningCommand
End If

oProc.StartInfo.UseShellExecute = False ' can't use shell
execute when we will be redirecting output.
oProc.StartInfo.ErrorDialog = False
oProc.StartInfo.CreateNoWindow = True
oProc.StartInfo.RedirectStandardError = True
oProc.StartInfo.RedirectStandardInput = bUseCmdExe
oProc.StartInfo.RedirectStandardOutput = True

If sWorkingDir <> "" Then
oProc.StartInfo.WorkingDirectory =
Path.GetFullPath(sWorkingDir)
If Not bUseCmdExe Then
' set the default path
ChDir(Path.GetFullPath(sWorkingDir))
oProc.StartInfo.FileName = Path.GetFullPath(sWorkingDir)
& sRunningCommand
End If
End If
oProc.Start()

If bUseCmdExe Then
swin = oProc.StandardInput
swIn.AutoFlush = True
End If

swOut = oProc.StandardOutput

swErr = oProc.StandardError

If bUseCmdExe Then
' The idea is to start a hidden command process, and feed it
the string to be executed
' via the redirected stdin.

swIn.WriteLine(sRunningCommand)
swIn.WriteLine("exit") ' after running, exit the invisible
command process.
End If

-------------------

Note: I have tried indicating that the output and err StreamReaders are
synchronized, as this creation code happens in a new thread which is also
used to monitor the readers. This did not have any effect on results.

Now, we already have one weird result (the output from the test app not
appearing when cmd.exe is used to run it from the interceptor). We are about
to get REALLY weird.

Recall that when NOT using cmd.exe, but running the console test app
directly via the interceptor, all expected lines were captured. Now let's
change the console app:

----------------
Sub Main()
Dim nLine As Integer

System.Console.WriteLine("RBAC console write test.")

For nLine = 1 To 20
System.Console.WriteLine(String.Format("Console write test --
line {0}.", nLine))

Threading.Thread.Sleep(100)
Next

System.Console.WriteLine("Done.")
End Sub
-------------------

The only change is the addition of Thread.Sleep after the first line. I then
ran this version by starting cmd.exe manually and got all expected lines.
But... now I'm going to run this in the interceptor, using the exact same
mode that worked before putting in the sleep. We capture:

------------------
RBAC console write test.
Console write test -- line 1.
------------------

That's right -- no line after the Sleep is captured. Even though the app
runs, and works fine in a manual cmd.exe, and even though nothing changed
other than the 100 ms sleep between lines, the redirected stdout no longer
gets any further characters on the output end of the pipe.

At this point I've tried many variations, including having my console test
app use a timer instead of sleep, doing various things with threading and so
forth, but anything that might result in any suspension of the line-writing
loop appears to have this effect on the output pipe, which is that nothing
comes out the other end.

This is a serious problem in that something this simple clearly should not
break the pipe. Remember, just writing the 20 lines to the output pipe
results in all 20 lines appearing at the other end of the pipe, but adding a
Sleep between the lines immediately halts output at the pipe. Whether or not
anything is actually being sent is unclear, but the application does
terminate normally in either case.

There's more -- I can really get this process messed up. First, let's take
the string we write and make it long -- by adding about 400 characters. Take
out the sleep:

--------------------

Sub Main()
Dim nLine As Integer

System.Console.WriteLine("RBAC console write test.")

For nLine = 1 To 20

System.Console.WriteLine(String.Format("1234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890Console
write test -- line {0}.", nLine))
Next

System.Console.WriteLine("Done.")
End Sub
---------------------

Run it in a command window and you get the expected output. Run it with the
interceptor, not via cmd.exe and get:

---------------

RBAC console write test.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 1.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 2.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 3.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 4.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 5.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 6.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 7.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 8.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 9.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 10.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 11.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 12.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 13.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 14.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 15.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 16.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 17.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 18.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 19.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 20.
Done.
-------------------------------

So this again is as expected, without the sleep on it. Put the sleep back
and as before we get just the first line (before the first Sleep):

----------------------------
RBAC console write test.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 1.
------------------------------

Ok - so what? Just as expected, right? Well, yes... except for the fact that
now, with the longer message, ConsoleAppTest actually doesn't even
terminate... it just stays in the task list! Before this, it always
terminated, but when this pipe problem occurs and "enough" is written to the
pipe, apparently the application hangs.

Next I changed the message, adding another 800 characters to the message.
Interestingly, I now get the first two messages! That is, I get the one just
before and just after the sleep, but no others:

--------------
RBAC console write test.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 1.
12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 Console write test -- line 2.
---------------------------------------

The application still, however, hangs and does not terminate. Apparently,
something is triggering the pipe to flush, but not consistently. By this time
you probably have started guessing I should just flush the stream.
----------------
Sub Main()
Dim nLine As Integer

System.Console.WriteLine("RBAC console write test.")

For nLine = 1 To 20

System.Console.WriteLine(String.Format("1234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 12345678901234567890123456789012345678901234567890 1234567890123456789012345678901234567890
Console write test -- line {0}.", nLine))
'System.Console.Out.Flush()
Threading.Thread.Sleep(100)
Next

System.Console.WriteLine("Done.")
End Sub
-------------------------

But this gives no change at all. Still getting the first 2 lines, then the
app doesn't terminate. Interestingly, I can change the sleep to 1000 and
watch the memory usage in task manager go up as the application writes to the
stream's buffer.
So that's it -- with Sleep, or anything might suspend, sleep, change
threads, etc. -- the pipe is broken. And remember, this is just a simple test
app. The actual application to be monitored is far more complex, but seems to
give the same result.

Why does the other end of the pipe work intermittently, and what can be done
to fix this?

I do have some support calls to use, and probably will need to, but this
message can serve to explain the problem.

Jul 22 '05 #1
4 5564
Oz,

Can you try this sample from me, that is in my idea simpler for standard
output from the console..
\\\
Process p = new Process();
ProcessStartInfo pi = new ProcessStartInfo();
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
pi.Arguments = "www.google.com";
pi.WorkingDirectory = "C:\\windows\\system32";
//this for nt* computers
pi.FileName = "ping";
p.StartInfo = pi;
p.Start();
System.IO.StreamReader sr = p.StandardOutput;
System.Text.StringBuilder sb = new System.Text.StringBuilder("");
int input = sr.Read();
while (input != -1)
{
sb.Append((char) input);
input = sr.Read();
}
MessageBox.Show(sb.ToString());
///

I hope this helps,

Cor
Jul 23 '05 #2
Oz,

Sorry, I gave you a C# answer, now I see that it had to be a VBNet sample.

\\\
Dim p As New Process
dim pi as new processstartinfo
pi.UseShellExecute = False
pi.RedirectStandardOutput = True
pi.Arguments = myargumentstring
pi.WorkingDirectory = myworkdirectorystring
pi..FileName =C:\myprogram
pi.startinfo = pi
p.Start()
Dim sr As IO.StreamReader = p.StandardOutput
Dim sb As New System.Text.StringBuilder("")
Dim input As Integer = sr.Read
Do Until input = -1
sb.Append(ChrW(input))
input = sr.Read
Loop
///

I hope this helps better,

Cor
Jul 23 '05 #3
Oz

Cor,

C# or VB is all ok with me. However, I did find part of the problem was that
I needed to have a separate thread to monitor stdout and stderr. That is, I
had a monitor thread looking at both of these, and some kind of race
condition between the two pipes would cause a hang -- like reading a line
from one which never quite completed, so that the loop never got around to
reading the other pipe, and thus a deadlock.

So... by having two threads (one for stdout, another for stderr), the
deadlock is avoided and my own console test app no longer has any problem
having its output captured. However, even though every console app or cmd.exe
command seems to now be capturable, the actual target application I
originally wanted to work with is STILL not showing its output!

So, here's some further info (and this would go to the C experts) -- the
console application is custom made and is a C application, but also is
compiled using a recent version of the Intel compiler, not MS. I have
examined the code, and he is using printf, which should write to stdout. I've
also verified that stdout is not being redirected or redefined in anyway.

So now I wonder if intel's runtime library does something differently. The
app does work of course under cmd.exe and shows its output, and can be
redirected to a file, so that would suggest the stdout pipe is hooked up as
expected, but still it is the only application I cannot capture stdout for.

So the problem originally observed about not capturing stdout, particularly
with the timing variations (which accentuated the race condition), is solved,
but there's something funny going on still.
"Cor Ligthert [MVP]" wrote:
Oz,

Sorry, I gave you a C# answer, now I see that it had to be a VBNet sample.

\\\
Dim p As New Process
dim pi as new processstartinfo
pi.UseShellExecute = False
pi.RedirectStandardOutput = True
pi.Arguments = myargumentstring
pi.WorkingDirectory = myworkdirectorystring
pi..FileName =C:\myprogram
pi.startinfo = pi
p.Start()
Dim sr As IO.StreamReader = p.StandardOutput
Dim sb As New System.Text.StringBuilder("")
Dim input As Integer = sr.Read
Do Until input = -1
sb.Append(ChrW(input))
input = sr.Read
Loop
///

I hope this helps better,

Cor

Jul 24 '05 #4
Oz
Things have progressed. There is still one problem.

At present, I can capture stderr and stdout from a console app. But some
console
apps behave differently than others. The Intel/C app I want to capture
appeared
to be buffering so that I could not retrieve the output until after it
completed (or,
possibly, when the buffer filled). Other apps I could capture line for line
as they
wrote to stdout. I created a .NET console app and its output could be captured
line-by-line by my capture software.

I was about to write it off as something odd about Intel's C compiler, but I
gave
it one more try. I wrote a super simple console program in VC++ 6:

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{
int n;
for(n=1; n < 20; n++)
{
printf("This is a test of just one line. Line %d\n", n);
Sleep(500);
};
return 0;
}

I expected to capture this line by line, but to my surprise it behaved
exactly as
the Intel/C app. It was almost certainly some type of buffering, so I added:

fflush(stdout);
right after the printf.

This fixed it -- I could capture line-by-line.

Now here's the problem: how is it that when these programs are executed
in a cmd.exe window, their output is displayed line by line? In .NET, when
I start these, it is with System.Diagnostics.Process.

The startinfo:
oProc.StartInfo.UseShellExecute = False ' can't use shell
execute when we will be redirecting output.
oProc.StartInfo.ErrorDialog = False
oProc.StartInfo.CreateNoWindow = True
oProc.StartInfo.RedirectStandardError = True
oProc.StartInfo.RedirectStandardInput = bUseCmdExe
oProc.StartInfo.RedirectStandardOutput = True

Pretty straight forward. Later, when reading:

Dim sr As StreamReader = oProc.StandardOutput
Dim sLine As String

sLine = sr.ReadLine
While Not (sLine Is Nothing)
RaiseEvent OutputText(sLine)
sLine = sr.ReadLine
End While

I've tried using peek to check if there are any characters before the
line completes, but it consistently blocks and doesn't say there's
anything until the process terminates (unless I use the fflush).

I've gone to the base stream and fooled with that, but found
nothing that would get the characters I needed. I'm beginning
to think I need to use the stream handle and Win32 APIs to
figure out something, which would be a drag.

So... how do I read the stream so that the data which is being
written to it appears at the other end? Remember, cmd.exe
IS doing just that, so it doesn't depend on me changing the application
in any way -- it must be something about the process itself.

One thought: perhaps when running under cmd.exe, the process
started is a child of cmd.exe, so cmd.exe can give it stdout directly,
and thus control the buffering of the pipe.

Is there some way in .NET for me to do something similar, or
to get better control of the stdout pipe?

Thanks!
Aug 13 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Mei | last post: by
11 posts views Thread by Marlene Stebbins | last post: by
18 posts views Thread by genc ymeri | last post: by
reply views Thread by psg | last post: by
2 posts views Thread by Maileen | last post: by
1 post views Thread by Alexander Inochkin | last post: by
reply views Thread by ivb | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.