如何将命令行界面放入 .net 表单应用程序中?

How do I put a command line interface inside a .net forms app?

我从事一个需要在面板中使用命令行的项目已经有一段时间了。 用户需要能够读取它并对其执行命令。

我有一些解决方案,其工作方式类似于 运行 一个单独的线程然后 运行 一个命令进程。然后我可以在控制台中读取命令行的内容,但是我不知道如何对它执行命令。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace MinecraftServerTool
{
    public partial class Home : Form
    {
        public Home()
        {
            InitializeComponent();
            Thread th = new Thread(JavaRun);
            th.Start();
            Thread.Sleep(100);
            this.ConsolePanel.Controls.Add(this.ServerConsole);
        }

private void JavaRun()
        {
            Process ps = new Process();
            ps.StartInfo.FileName = "cmd.exe";
            ps.StartInfo.UseShellExecute = false;
            ps.StartInfo.RedirectStandardInput = true;
            ps.StartInfo.RedirectStandardOutput = true;
            ps.Start();
            ps.StandardInput.WriteLine("dir");
            id = ps.Id;

            this.ServerConsole = new System.Windows.Forms.ListBox();
            this.ServerConsole.BackColor = System.Drawing.SystemColors.ControlLight;
            this.ServerConsole.ForeColor = System.Drawing.SystemColors.ControlDarkDark;
            this.ServerConsole.FormattingEnabled = true;
            this.ServerConsole.ItemHeight = 16;
            this.ServerConsole.Location = new System.Drawing.Point(35, 265);
            this.ServerConsole.Name = "Console";
            this.ServerConsole.Size = new System.Drawing.Size(250, 84);
            this.ServerConsole.TabIndex = 17;
            CmdOpen = true;

            while (CmdOpen == true)
            {
                Console.WriteLine(ps.StandardOutput.ReadLine());
                if (ps.HasExited == true)
                {
                    CmdOpen = false;                    
                }
            }
        Thread.CurrentThread.Abort();
        }
    }
}

如果你想复制它,上面的代码进入标准 windows 表单 c# .net 应用程序的主 (formname).cs 文件。目前它应该只创建一个列表框,打开一个新的命令提示符并将该命令提示符的输出放在控制台中。不幸的是,输出将在应用程序控制台中,而不是在我创建的列表框中(不幸的是)。

我的问题是,我应该继续创建一个运行命令提示符并写入输出的新线程,还是有什么方法可以将命令提示符准确地完全集成到带有 NuGet 包之类的面板中?我还可以拥有一个两个线程都可以访问的全局变量吗?

不好意思这个问题写的很奇怪

Process.OutputDataReceived 是重定向输出的关键。

public partial class Home : Form
{
    public Home()
    {
        InitializeComponent();
        JavaRun();
    }

    private void JavaRun()
    {
        Task.Factory.StartNew(() =>
        {
            Process ps = new Process();
            ps.StartInfo = new ProcessStartInfo("cmd.exe")
            {
                WorkingDirectory = @"C:\src",
                RedirectStandardError = true,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
                CreateNoWindow = true,
            };
            //Here is button click event, but you can give any event that you want to trigger command
            this.btnGo.Click += (s, e) => ps.StandardInput.WriteLine(this.txtCommand.Text); //output your command to process.
            this.btnExit.Click += (s, e) => ps.Kill();


            ps.ErrorDataReceived += (s, e) => Log(e.Data);
            ps.OutputDataReceived += (s, e) => Log(e.Data);
            ps.Start();
            ps.BeginErrorReadLine();
            ps.BeginOutputReadLine();
            ps.StandardInput.WriteLine("dir");
            ps.StandardInput.WriteLine("cd..");
            ps.WaitForExit();
        });
    }

    private void Log(string value)
    {
        if (ServerConsole.IsDisposed)
        {
            return;
        }

        if (ServerConsole.InvokeRequired)
        {
            //allow thread to update main frame.
            ServerConsole.Invoke(new Action(() =>
            {
                ServerConsole.Items.Add(value);
            }));
        }
        else
        {
            ServerConsole.Items.Add(value);
        }
    }
}

顺便说一句,关于你第一个关于 Thread 的问题,这是避免阻塞主框架所必需的,这里我使用 Task.Factory.StartNew 来缩短代码,但这不是重定向输出的原因.