473,705 Members | 3,166 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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.Diagnost ics.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(Strin g.Format("Conso le 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\N ET\ConsoleAppTe st\ConsoleAppTe st\bin>consoleA ppTest.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\N ET\ConsoleAppTe st\ConsoleAppTe st\bin>dir
Volume in drive C has no label.
Volume Serial Number is E8B4-4400

Directory of C:\00sts\RBAC\N ET\ConsoleAppTe st\ConsoleAppTe st\bin

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\N ET\ConsoleAppTe st\ConsoleAppTe st\bin>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\N ET\ConsoleAppTe st\ConsoleAppTe st\bin>consolea pptest
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 .UseShellExecut e = False ' can't use shell
execute when we will be redirecting output.
oProc.StartInfo .ErrorDialog = False
oProc.StartInfo .CreateNoWindow = True
oProc.StartInfo .RedirectStanda rdError = True
oProc.StartInfo .RedirectStanda rdInput = bUseCmdExe
oProc.StartInfo .RedirectStanda rdOutput = True

If sWorkingDir <> "" Then
oProc.StartInfo .WorkingDirecto ry =
Path.GetFullPat h(sWorkingDir)
If Not bUseCmdExe Then
' set the default path
ChDir(Path.GetF ullPath(sWorkin gDir))
oProc.StartInfo .FileName = Path.GetFullPat h(sWorkingDir)
& sRunningCommand
End If
End If
oProc.Start()

If bUseCmdExe Then
swin = oProc.StandardI nput
swIn.AutoFlush = True
End If

swOut = oProc.StandardO utput

swErr = oProc.StandardE rror

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(Strin g.Format("Conso le write test --
line {0}.", nLine))

Threading.Threa d.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(Strin g.Format("12345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 67890Console
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.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 1.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 2.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 3.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 4.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 5.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 6.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 7.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 8.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 9.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 10.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 11.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 12.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 13.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 14.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 15.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 16.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 17.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 18.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le write test -- line 19.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le 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.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890Conso le 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.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 Console write test -- line 1.
123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 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(Strin g.Format("12345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 123456789012345 678901234567890 1234567890
Console write test -- line {0}.", nLine))
'System.Console .Out.Flush()
Threading.Threa d.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 6098
Oz,

Can you try this sample from me, that is in my idea simpler for standard
output from the console..
\\\
Process p = new Process();
ProcessStartInf o pi = new ProcessStartInf o();
pi.UseShellExec ute = false;
pi.RedirectStan dardOutput = true;
pi.Arguments = "www.google.com ";
pi.WorkingDirec tory = "C:\\windows\\s ystem32";
//this for nt* computers
pi.FileName = "ping";
p.StartInfo = pi;
p.Start();
System.IO.Strea mReader sr = p.StandardOutpu t;
System.Text.Str ingBuilder sb = new System.Text.Str ingBuilder("");
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 processstartinf o
pi.UseShellExec ute = False
pi.RedirectStan dardOutput = True
pi.Arguments = myargumentstrin g
pi.WorkingDirec tory = myworkdirectory string
pi..FileName =C:\myprogram
pi.startinfo = pi
p.Start()
Dim sr As IO.StreamReader = p.StandardOutpu t
Dim sb As New System.Text.Str ingBuilder("")
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 processstartinf o
pi.UseShellExec ute = False
pi.RedirectStan dardOutput = True
pi.Arguments = myargumentstrin g
pi.WorkingDirec tory = myworkdirectory string
pi..FileName =C:\myprogram
pi.startinfo = pi
p.Start()
Dim sr As IO.StreamReader = p.StandardOutpu t
Dim sb As New System.Text.Str ingBuilder("")
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.Diagnost ics.Process.

The startinfo:
oProc.StartInfo .UseShellExecut e = False ' can't use shell
execute when we will be redirecting output.
oProc.StartInfo .ErrorDialog = False
oProc.StartInfo .CreateNoWindow = True
oProc.StartInfo .RedirectStanda rdError = True
oProc.StartInfo .RedirectStanda rdInput = bUseCmdExe
oProc.StartInfo .RedirectStanda rdOutput = True

Pretty straight forward. Later, when reading:

Dim sr As StreamReader = oProc.StandardO utput
Dim sLine As String

sLine = sr.ReadLine
While Not (sLine Is Nothing)
RaiseEvent OutputText(sLin e)
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
3456
by: Marcus | last post by:
Hello, I recently converted all my existing MyISAM tables to InnoDB tables through phpmyadmin. I noticed some strange behavior whenever I would refresh the screen, as phpmyadmin would report different numbers for the cardinality of the primary key (i.e. one minute it would say cardinality 388, then 244 on refresh, then something else), and it would report different values for the number of rows when mousing over the table names on the...
1
1323
by: Mei | last post by:
Hi, I'm running ASP under IIS 6 with Tomcat. During the process, Tomcat will forward to an ASP page with some data and those data will be written to MS SQL and display some information in that particular ASP page. The Servlet has no unsafe code. The strange thing is that all the data is written correctly in the MS SQL with correct user and related information but the data might become blank or send to different users in that ASP page....
11
1669
by: Marlene Stebbins | last post by:
Something very strange is going on here. I don't know if it's a C problem or an implementation problem. The program reads data from a file and loads it into two arrays. When xy, x, y, *xlist and *ylist are ints or floats there is no apparent problem. If these variables are doubles, the program crashes. Furthermore, the crashes occur only when xlist and ylist are free()ed. When the above variables are doubles and the calls to free() are...
18
1617
by: genc ymeri | last post by:
Hi, I just noticed that while trying to run this code : MessageBox.Show("Hello"); the message box pops up but shows no string/message in it. (expecting the "Hello" string). Even the "OK" string in the button itself in dialog box doesn't show. I tried to write "Hello" string in the caption/text of the button or the
0
1006
by: psg | last post by:
Hello! I was going through help topics under IDE. Once when I tried to close Help tab it did not close, but it opened itself in a new tab. So I got two Help tabs with the same content. When I tried to close it once again both tabs were redirected to http://msdn.microsoft.com ... I noticed that strange behavior some time ago so I closed IDE and reopened my solution (AFAIR such closing of IDE helped me last time), but to my surprise new...
2
1222
by: Maileen | last post by:
Hi, I have some strange behavior in my application. Let's say I have 2 buttons and 1 Textbox. 1. when i click on button1, it writes "hello world" in my textbox. i see it. 2. after that, i click on button2 to take the text of my textbox and do something with it. but instead of that, button2 returns me an empty
5
668
by: Oz | last post by:
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,...
1
1507
by: Alexander Inochkin | last post by:
Hi! I found same strange behavior of ASP.NET. It is possible this is the bug. Follow the steps:
0
3572
by: ivb | last post by:
Hi all, I am using DB2 8.1.11.1 on NT with ASP.NET 1.1 When application make connection to database (via ADO.NET), it set "Connection timeout" parameter to 30 seconds. After, when my webpage requests database, and query execution time exceeds 30 seconds, the following error reported: ===
0
8768
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9274
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9139
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9034
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8979
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6606
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4704
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3138
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2083
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.