0

I've got a problem with showing results of cmd commands to richtextbox. So far, I have this code:

private void richTextBox2_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            e.Handled = true;
            e.SuppressKeyPress = true;
                ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
                cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
                cmdStartInfo.RedirectStandardOutput = true;
                cmdStartInfo.RedirectStandardError = true;
                cmdStartInfo.RedirectStandardInput = true;
                cmdStartInfo.UseShellExecute = false;
                cmdStartInfo.CreateNoWindow = true;

                Process cmdProcess = new Process();
                cmdProcess.StartInfo = cmdStartInfo;
                cmdProcess.OutputDataReceived += cmd_DataReceived;
                cmdProcess.EnableRaisingEvents = true;
                cmdProcess.Start();
                cmdProcess.BeginOutputReadLine();
                cmdProcess.BeginErrorReadLine();

                cmdProcess.StandardInput.WriteLine(richTextBox2.Text);     
                cmdProcess.StandardInput.WriteLine("exit");                  

                cmdProcess.WaitForExit();

                richTextBox1.Text = richTextBox1.Text + cmd_DataReceived + Environment.NewLine;

        }
    }

static void cmd_DataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine("Output from other process");
        Console.WriteLine(e.Data);
    }

I've tried replacing "Console.WriteLine(e.Data);" with "richTextBox1.Text = richTextBox1.Text + (e.Data);" but it wouldn't be accepted. I also tried "richTextBox1.Text = richTextBox1.Text + cmd_DataReceived"; But that didn't work iether. Then I tried replacing console.writeline with messagebox.show(e.data) but again.. nope The commands work, but it won't display

I know I copied most of the code, and it's probably meant for a console application.

Please help

KrisPus
  • 53
  • 2
  • 13
  • It is not clear what you are trying to do here. You write the content of the richtextbox to the InputStream so it seems that you want to write the arguments for the cmd.exe in the richtextbox and then pass them to the command prompt, but your question ask to display the results to the richtextbox. By the way there is no output in a call to CMD.EXE without parameters. – Steve Jul 21 '16 at 21:23
  • hmm. then this is nearly impossible except if I add all the command prompt answers to all the commands. And yes, i think you understood it right. – KrisPus Jul 21 '16 at 21:27
  • I was helping someone else do something very similar. Your code looks fine, I *think* your only issue is that events run in their own thread and you can't update the UI from any thread, you can only update it from the UI thread. A bit out of my element here, but you need to use Invoke or BeginInvoke, and possibly with a Dispatcher, e.g., [here](http://stackoverflow.com/questions/4446048/how-to-update-textboxes-in-main-thread-from-another-thread) and [here](http://stackoverflow.com/questions/19009174/dispatcher-invoke-vs-begininvoke-confusion). – Quantic Jul 21 '16 at 21:56
  • Also you don't need to set `EnableRaisingEvents`, that's only needed if you are going to subscribe to the `.Exited` event. Read [here](https://msdn.microsoft.com/en-us/library/system.diagnostics.process.enableraisingevents(v=vs.110).aspx). It actually has nothing to do with redirecting stdin/stdout/stderr to event handlers. – Quantic Jul 21 '16 at 22:00

1 Answers1

1

As you're waiting for the process to exit with cmdProcess.WaitForExit, cmd_DataReceived is getting all the data. This means you're going to need to store the data you get from the callback, and after WaitForExit ends, you can then set the text box with the contents of the stored data.

One simple way is to use a StringBuilder:

    // Have a reference to a stringbuilder that both functions can see
    StringBuilder m_output;

    private void richTextBox2_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            // Before the process starts, create a new stringbuilder
            m_output = new StringBuilder();

            e.Handled = true;
            e.SuppressKeyPress = true;
            ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
            cmdStartInfo.FileName = @"C:\Windows\System32\cmd.exe";
            cmdStartInfo.RedirectStandardOutput = true;
            cmdStartInfo.RedirectStandardError = true;
            cmdStartInfo.RedirectStandardInput = true;
            cmdStartInfo.UseShellExecute = false;
            cmdStartInfo.CreateNoWindow = true;

            Process cmdProcess = new Process();
            cmdProcess.StartInfo = cmdStartInfo;
            cmdProcess.OutputDataReceived += cmd_DataReceived;
            cmdProcess.EnableRaisingEvents = true;
            cmdProcess.Start();
            cmdProcess.BeginOutputReadLine();
            cmdProcess.BeginErrorReadLine();

            cmdProcess.StandardInput.WriteLine(richTextBox2.Text);
            cmdProcess.StandardInput.WriteLine("exit");

            cmdProcess.WaitForExit();

            // And now that everything's done, just set the text
            // to whatever's in the stringbuilder
            richTextBox1.Text = m_output.ToString();

            // We're done with the stringbuilder, let the garbage
            // collector free it
            m_output = null;
        }
    }

    // Note: This is no longer a static method so it has
    // access to the member variables, including m_output
    void cmd_DataReceived(object sender, DataReceivedEventArgs e)
    {
        Debug.WriteLine("Output from other process");
        Debug.WriteLine(e.Data);

        // Add the data, one line at a time, to the string builder
        m_output.AppendLine(e.Data);
    }
Anon Coward
  • 9,784
  • 3
  • 26
  • 37
  • It worked!, even tho I'm getting "Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved." before the text, I can make a filter string for that :) – KrisPus Jul 22 '16 at 00:09
  • I added the string: string RAW = m_output.ToString().Split(new string[] { ">" }, StringSplitOptions.None).Last(); string RAW2 = RAW.Split(new string[] { richTextBox2.Text + " & exit" }, StringSplitOptions.RemoveEmptyEntries).Last(); But ended up with many empty lines, but it's fine – KrisPus Jul 22 '16 at 12:44