title: Get .NET Process object to flush input stream continously?
body: <p>I am trying to change my class library that talks to the Mercurial command line client, and new in the 1.9 client is the ability to spin up a server and talk to it over the standard input/output pipes. This is really promising since one of the major headaches of using the Mercurial command line client is that since it is written in Python, there's a bit of overhead spinning up the client, even for just asking it for its version.</p>
  
  <p>However, there is one problem. Up until now I have retrieved the output from the command line client by reading the standard output/error, and when the process exits, the streams flush and I can read the end of the stream.</p>
  
  <p>However, in this new mode, the process will dump a lot of text to the standard error/output, and then sit around waiting for the next command. Great for reducing overhead, but lousy since .NET buffers those streams.</p>
  
  <p>In other words, since the process does not exit, I do not get the last portion of that output until:</p>
  
  <ol>
  <li>I ask the process to exit</li>
  <li>I issue another command</li>
  </ol>
  
  <p>Is there a way for me to</p>
  
  <ol>
  <li>Ask the buffer to flush, meaning that I get whatever is in the buffer, even if it is not enough to make the buffer flush by itself?</li>
  <li>If not, can I set the buffer-size to 1 character?</li>
  <li>Anything else I can do?</li>
  </ol>
  
  <p>I can deal with P/Invoke if that is what it takes.</p>
  
  <p>Here's a <a href="http://linqpad.net" rel="nofollow">LINQPad</a> proof-of-concept program that would illustrate:</p>
  
  <p>What it does is spin up a command prompt and feed it the DIR command, however notice that not until those 10 seconds have elapsed inside the loop does the program output the "C:>" prompt that the command prompt outputted right after producing the directory listing.</p>
  
  <p>In other words, this is what the command prompt does:</p>
  
  <ol>
  <li>Produce directory listing</li>
  <li>Ask for another command by prompting "C:>\"</li>
  </ol>
  
  <p>However, this is what the program below sees:</p>
  
  <ol>
  <li>Produce directory listing</li>
  <li>(wait 10 seconds)</li>
  <li>Close the input stream</li>
  <li><p>See the prompt</p>
  
  <p>void Main()
  {
      string clientExecutablePath = "cmd.exe";</p>
  
  <pre><code>var psi = new ProcessStartInfo();
  psi.FileName = clientExecutablePath;
  psi.RedirectStandardError = true;
  psi.RedirectStandardInput = true;
  psi.RedirectStandardOutput = true;
  psi.CreateNoWindow = true;
  psi.WorkingDirectory = @"C:\";
  psi.WindowStyle = ProcessWindowStyle.Hidden;
  psi.UseShellExecute = false;
  psi.ErrorDialog = false;
  psi.StandardErrorEncoding = Encoding.GetEncoding("Windows-1252");
  psi.StandardOutputEncoding = Encoding.GetEncoding("Windows-1252");
  
  var p = Process.Start(psi);
  
  var input = p.StandardInput;
  var output = p.StandardOutput;
  var error = p.StandardError;
  
  Action&lt;StreamReader, string&gt; reader = delegate(StreamReader streamReader, string prefix)
  {
      string line;
      while ((line = streamReader.ReadLine()) != null)
      {
          Debug.WriteLine(prefix + line);
      }
  };
  
  IAsyncResult outputReader = reader.BeginInvoke(output, "o: ", null, null);
  IAsyncResult errorReader = reader.BeginInvoke(error, "e: ", null, null);
  
  input.Write("dir\n");
  input.Flush();
  
  while (!p.HasExited)
  {
      Thread.Sleep(10000);
      input.Close();
  }
  
  reader.EndInvoke(outputReader);
  reader.EndInvoke(errorReader);
  </code></pre>
  
  <p>}</p></li>
  </ol>