简体   繁体   中英

Embedding a CMD terminal in a C# Winforms application

What I intend to do is build an application which, among other things, will have a command line embedded in it just like some IDEs do (something I find extremely useful).

This is the code that I have so far, do note that it's a Winforms project:

public partial class Form1 : Form
    {
        Process p = new Process();
        ProcessStartInfo info = new ProcessStartInfo();

        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            info.FileName = "cmd.exe";
            info.RedirectStandardInput = true;
            info.RedirectStandardOutput = true;
            info.RedirectStandardError = true;
            info.UseShellExecute = false;
            info.CreateNoWindow = true;

            p.StartInfo = info;
            p.Start();
        }

        private void button1_Click(object sender, EventArgs e) {
            using(StreamWriter sw = p.StandardInput) {
                if(sw.BaseStream.CanWrite) {
                    sw.WriteLine(textBox1.Text);
                }
            }
            textBox2.Text = p.StandardOutput.ReadToEnd();
            textBox3.Text = p.StandardError.ReadToEnd();
            p.WaitForExit();
        }
    }
}

As you can see there are 3 textboxes and one button:

  • textbox1 is for entering the command
  • textbox2 is for stdout
  • textbox3 is for stderr

On to my problem:

I can only input one command because after executing it, my CMD window vanishes. I know it dies off because I've set info.CreateNoWindow = false; and it indeed vanishes and if I try to enter another command I get an exception.

How would I go on about keeping my CMD window 'alive' so that I can use it as much as I please? In short I want to truly mimic CMD behavior.

Feel free to ask for more information if something is not clear.

Extra info/What I tried:

I've tried adding info.Attributes = "/K"; since I know that /K should keep the CMD alive. I've also read that p.WaitForExit(); should keep the CMD alive, but from what I figured this is only for the purpose of reading the output. Needless to say, I do not need that since I'm already redirecting its output. Neither of these solutions work but it is entirely possible that I'm using them the wrong way.

I need that process alive so I can easily navigate using cd and executing a sequence of commands when needed, such as when accessing ftp or mysql . I know I can work around these two examples with parameters, but not for every application. In short, spawning a new process every time is not something I want. I want that CMD interface to be up at all times.

The cmd process dies after

using(StreamWriter sw = p.StandardInput) {
    if(sw.BaseStream.CanWrite) {
        sw.WriteLine(textBox1.Text);
    }
}

But I cannot pinpoint why.

What CMD console provides is an interface to execute predefined functions (in System32 or in %PATH%). Process class also have same capabilities ,what you can do is as the user enters command text and presses return key in textbox2 (which can be multi-lined, black-background, white text) you can pass the command text to Process p = new Process(); and append the result so it looks like single cmd session. Now before passing the whole command text we need to separate arguments (if any) which is text appearing after first space. Example:

SHUTDOWN /S /T 10

where Shutdown will be filename and /S /T 10 will be arguments.

Before executing set default directory of ProcessStartInfo:-

_processStartInfo.WorkingDirectory = @"%Path%";

Otherwise default will be System32 folder.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM