在C#Winforms应用程序中嵌入CMD终端

在C#Winforms应用程序中嵌入CMD终端,c#,process,createprocess,C#,Process,Createprocess,我打算做的是构建一个应用程序,其中包括一个嵌入命令行的应用程序,就像某些IDE所做的那样(我发现这非常有用) 这是我到目前为止的代码,请注意这是一个Winforms项目: public partial class Form1 : Form { Process p = new Process(); ProcessStartInfo info = new ProcessStartInfo(); public Form1() {

我打算做的是构建一个应用程序,其中包括一个嵌入命令行的应用程序,就像某些IDE所做的那样(我发现这非常有用)

这是我到目前为止的代码,请注意这是一个Winforms项目:

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();
        }
    }
}
如您所见,有3个文本框和一个按钮:

  • textbox1用于输入命令
  • textbox2用于标准输出
  • textbox3是用于stderr的
关于我的问题:

我只能输入一个命令,因为在执行它之后,我的CMD窗口消失了。我知道它会消失,因为我设置了
info.CreateNoWindow=false,它确实消失了,如果我尝试输入另一个命令,我会得到一个异常

我将如何继续保持我的CMD窗口“活动”,以便我可以尽可能多地使用它?简而言之,我想真正模仿CMD的行为。

如果有不清楚的地方,请随时询问更多信息

额外信息/我尝试的内容:

我已尝试添加
info.Attributes=“/K”
因为我知道
/K
应该让CMD保持活动状态。我也读过
p.WaitForExit()
应该让CMD保持活动状态,但根据我的计算,这只是为了读取输出。不用说,我不需要它,因为我已经重定向了它的输出。这两种解决方案都不起作用,但我完全有可能用错了方法

我需要该进程处于活动状态,以便在需要时使用
cd
轻松导航并执行一系列命令,例如访问
ftp
mysql
时。我知道我可以使用参数处理这两个示例,但不是针对每个应用程序。简而言之,我并不希望每次都产生一个新的进程。我希望CMD接口一直处于打开状态

cmd进程在之后死亡

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

但我无法指出原因

CMD控制台提供的是一个执行预定义功能的接口(在System32或%PATH%中)。Process类也具有相同的功能,您可以做的是,当用户输入命令文本并按下textbox2中的返回键(可以是多行、黑色背景、白色文本)时,您可以将命令文本传递给
Process p=new Process()
并附加结果,使其看起来像单个cmd会话。现在,在传递整个命令文本之前,我们需要分离参数(如果有),这些参数是出现在第一个空格之后的文本。例如:

SHUTDOWN /S /T 10
其中Shutdown将是filename,/S/t10将是参数

在执行设置ProcessStartInfo的默认目录之前:-

_processStartInfo.WorkingDirectory = @"%Path%";

否则,默认设置为System32文件夹

使用
语句导致
p.StandardInput
被处理(
sw
只是对它的引用)。不要这样做-当你不再需要它的时候,处理它。@PieterWitvoet谢谢你的回答。所以当我离开
使用
范围时,p基本上被处理掉了?如果没有
using
语句,我将如何继续使用StreamWriter?我已尝试在
Form1\u Load
方法中声明StreamWriter,然后访问输出
p.StandardOutput
,但我的应用程序毫无例外地挂起。请您详细说明一下好吗?无论您使用的是什么,都会在
using
块的末尾处理—因此每次输入命令时,您的代码都会处理流程的标准输入。您实际上是在处理对象的一部分,并期望它继续像以前一样工作。只需使用
语句删除该
sw
不是您负责的新流编写器-它是对
p.StandardInput
的引用。Disposing
p
将为您处理这些流编写器。@PieterWitvoet在您编写上一条评论时,我一直在尝试使用StreamWriter而不使用
using
块。调试器清楚地显示命令是向进程发送的,但是我的应用程序在尝试读取输出时挂起,即la
textBox2.Text=p.StandardOutput.ReadToEnd()。不用说,我的应用程序中没有输出。但有趣的是:如果我手动关闭CMD窗口(生成的进程),我的应用程序将收到输出。但是我不能再使用这个过程了,因为我关闭了它。你知道为什么会发生这种情况吗?我假设
ReadToEnd
挂起是因为流没有结束。在你读到一些东西之前,先试试看这个流。这实际上是我在一个C++应用程序中想到的一个想法。不幸的是,这只是真实事物的一个影子,一个模拟,一个解决办法。这不是一个实际的解决办法。这正是我用C#重写类似应用程序的原因。但是谢谢你的意见,我会把这作为最后的手段。