如何将命令行界面放入 .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
来缩短代码,但这不是重定向输出的原因.
我从事一个需要在面板中使用命令行的项目已经有一段时间了。 用户需要能够读取它并对其执行命令。
我有一些解决方案,其工作方式类似于 运行 一个单独的线程然后 运行 一个命令进程。然后我可以在控制台中读取命令行的内容,但是我不知道如何对它执行命令。
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
来缩短代码,但这不是重定向输出的原因.