13

This question has been asked more than once before, but I have not found a satisfactory answer in any of those discussions.

I am launching a command-line process that produces a real-time measurement to STDOUT, producing a new result approximately every second. Using System.Diagnostics.Process.StandardOutput results in completely unacceptable lag (over 20 seconds) as the STDOUT data works through the 4k buffer in the Process.StandardOutput StreamReader, and there doesn't seem to be any way to get around this.

Calling Process.StandardOutput.BaseStream.Flush() doesn't work.

I've tried doing a byte-by-byte synchronous read of Process.StandardOutput, but I'm still 4k behind the actual output.

Can anyone at least verify for me that it is possible to somehow overcome all of the buffering issues I am having with redirecting STDOUT, and receive the data in my application as soon as it would have appeared in the shell window? Can I inherit from the Process class and change how the StandardOutput streamreader behaves? Do I need to be looking at raw WINAPI calls?

Somehow, this has to get done, even if I end up writing unmanaged C++ to launch the task and consume the output, and linking that in. Any help is much appreciated; I'm at my wit's end...

Edit: It appears that what I need is a .Net implementation of the "expect" libraries that are available for C/C++, Perl, Python, and Java (those are the only ones I have found so far). Does anyone know if such a beast exists?

5
  • 1
    sucks you never got a good answer to this question... Commented Jul 11, 2011 at 21:44
  • Yeah. I ended up acquiring the source code to the external command, and recompiling it with explicit STDOUT buffer flushing. I'd still like to solve the original problem, though. I toyed with writing a .Net Expect implementation myself, but recompiling the external tool seemed like a better way to avoid having my boss yell at me. Commented Jul 20, 2011 at 17:42
  • I've been struggling with the same problem. I'm reading the console output in a separate thread (or actually 2: 1 for stderr, 1 for stdout). As it turns out, the StandardOutput only buffers when you're using calls like Peek, which will return -1 in the process. If you simply use ReadLine or Read with 1 byte, it'll work just fine, and you won't have trouble with the buffering. Commented Aug 6, 2014 at 14:16
  • @StefandeBruijn - no, that won't work in this situation. The issue is that printf-like functions have two modes - one "console" mode, where data is output immediately, and another "batch" mode where data is internally buffered so fewer file I/O operations are needed. When the external process is launched and STDOUT is redirected, it is running in "batch" mode - using a buffer that is entirely internal to the child process. So, the trick (which I never figured out) is how to trick the process into running in "console" mode so that data prints immediately, while still redirecting the output. Commented Aug 6, 2014 at 15:10
  • Are you sure? I thought something like that was also the case for msbuild, but it turns out my current solution works there, even though all 'indicators' like peek and blocking booleans tell me it shouldn't work. Commented Aug 6, 2014 at 16:11

1 Answer 1

1

"[I]s there a way to launch it such [that] it doesn't realize it is being redirected?" YES: that is exactly the domain of Expect. I know of no .Net implementation; it's surely feasible, though ...

Sign up to request clarification or add additional context in comments.

1 Comment

Very challenging due to the way Windows works internally! (Well, not with Mono on Unix where you've got access to real virtual terminals, but that's another story.) Expect for Windows uses some kind of funky debugging mode to make it all work, and AIUI was a really gross hack. It would probably be easier to use actual expect itself (running the unbuffer script) in a subprocess; yes, it makes deployment harder, but it does have a really good chance of working. Except with telnet.exe; that's a special (and extra-sucky) case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.