Joshua Evensen
Joshua Evensen

Reputation: 1566

i'm writing a wrapper for cmd but am having trouble with redirecting standard input

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);
        }
    }
}

Upvotes: 2

Views: 829

Answers (2)

ferosekhanj
ferosekhanj

Reputation: 1074

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);
            }
        }
    }

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1504122

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?

Upvotes: 0

Related Questions