views:

63

answers:

2

OK so here is what I'm doing -- I want to write a .net app that redirects standard out / in to a richtextbox. I've got it working pretty well, but once I add standard input into the mix my read commands freeze up. Here is the relevant code from within my form.

        Shell = new Process();
        Shell.StartInfo.FileName = "cmd";

        Shell.StartInfo.UseShellExecute = false;
        Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Shell.StartInfo.CreateNoWindow = true;

        //Shell.StartInfo.RedirectStandardInput = true;
        Shell.StartInfo.RedirectStandardOutput = true;
        Shell.StartInfo.RedirectStandardError = true;

        Shell.EnableRaisingEvents = true;
        Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
        Shell.ErrorDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);

        Shell.Start();

        Timer consoleReader = new Timer();
        consoleReader.Interval = 200;
        consoleReader.Tick += new EventHandler(consoleReader_Tick);
        consoleReader.Start();
    }

    void consoleReader_Tick(object sender, EventArgs e)
    {
        textArea.AppendText(Shell.StandardOutput.ReadToEnd());
    }

I've also tried doing this the Asynchronous reading methods available in the Process class but, again, once I add standardinputredirect = true into the mix, it will hang up after reading maybe a line or so.

Any ideas guys?

[[EDIT]] Ok, so here is a sample program. I moved this code into a console app to simplify things a bit. Why is this broken?

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace TestAsConsoleApp
{
    class Program
    {
        static Process Shell;
        static void Main(string[] args)
        {
            Shell = new Process();
            Shell.StartInfo.FileName = "cmd";

            Shell.StartInfo.UseShellExecute = false;
            Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            Shell.StartInfo.CreateNoWindow = true;

            Shell.StartInfo.RedirectStandardInput = true;
            Shell.StartInfo.RedirectStandardOutput = true;
            Shell.StartInfo.RedirectStandardError = true;

            Shell.Start();

            Shell.EnableRaisingEvents = true;
            Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
            Shell.BeginOutputReadLine();

            Shell.WaitForExit();
        }

        static void Shell_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (e.Data != null)
                Console.WriteLine(e.Data);
        }
    }
}
A: 

If you're reading asynchronously, you don't need to read synchronously as well - and your synchronous code is broken, as it blocks until all the output has been received, which you shouldn't do within a UI thread. I'd just go for the asynchronous code if I were you.

Now, what are you trying to do with the console? You say that standard input is causing problems - what are you trying to write to it? Are you explicitly flushing?

Jon Skeet
well i wasnt trying to simultaneously read synchronously. it was an alternate approach i attempted.i didnt know readtoend blocked though.
Joshua Evensen
also i should clarify, writing to output itself isnt the act thats breaking things -- its just that when i set that bool to true, reading stops after like two lines.
Joshua Evensen
@Joshua: But is the process you're launching expecting some input? If it is, that would explain why it's blocking.
Jon Skeet
It's CMD, so yes, I guess?
Joshua Evensen
@Joshua: So are you actually *giving* it that input, and flushing? It would really help if you could provide a short but complete program which demonstrates the problem.
Jon Skeet
Updated original post with broken code sample.
Joshua Evensen
A: 

The revised program doesn't looks to be broken. You create a process request all the streams to be redirected. You trigger async reading of the created process output. Then you just wait. In your case the created cmd.exe doesn't get anything in its input stream so it will not produce any output. May be try the below program. Run it and give some commands like dir etc it will produce the output. Hope I didn't misunderstood your problem.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;

    namespace TestAsConsoleApp
    {
        class Program
        {
            static Process Shell;
            static void Main(string[] args)
            {
                Shell = new Process();
                Shell.StartInfo.FileName = "cmd";

                Shell.StartInfo.UseShellExecute = false;
                Shell.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                Shell.StartInfo.CreateNoWindow = true;

                Shell.StartInfo.RedirectStandardInput = true;
                Shell.StartInfo.RedirectStandardOutput = true;
                Shell.StartInfo.RedirectStandardError = true;

                Shell.Start();
                //Shell.StandardInput.WriteLine("dir");

                Shell.EnableRaisingEvents = true;
                Shell.OutputDataReceived += new DataReceivedEventHandler(Shell_OutputDataReceived);
                Shell.BeginOutputReadLine();
//read input from your programs input and forward that to the created cmd 's input
                do
                {
                    string aLine = Console.ReadLine();
                    Shell.StandardInput.WriteLine(aLine);
                    if (aLine.ToLower() == "exit")
                        break;
                }while(true);

                Shell.WaitForExit();
            }

            static void Shell_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                if (e.Data != null)
                    Console.WriteLine(e.Data);
            }
        }
    }
ferosekhanj
Have you tried actually running this? Does it work on your machine and not mine?
Joshua Evensen
Yes it works perfect for me without any issue. What happens in your case?
ferosekhanj