在 C# 中,打开和显示 CMD 进程主要通过 System.Diagnostics.Process
类实现,核心是配置进程启动信息并处理其输入输出。以下结合代码细节说明具体实现方式:
1. 启动 CMD 进程(隐藏原始窗口)
代码通过 ProcessStartInfo
配置 CMD 进程的启动参数,关键是隐藏原始 CMD 窗口并重定向输入输出:
// 配置进程启动信息
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe", // 指定要启动的程序为CMD
UseShellExecute = false, // 禁用外壳程序,允许重定向输入输出
RedirectStandardInput = true, // 重定向标准输入(允许向CMD发送命令)
RedirectStandardOutput = true, // 重定向标准输出(捕获CMD的执行结果)
RedirectStandardError = true, // 重定向错误输出(捕获错误信息)
CreateNoWindow = true, // 不显示CMD的原始窗口
StandardOutputEncoding = Encoding.Default, // 匹配系统默认编码
StandardErrorEncoding = Encoding.Default
};
// 创建进程对象并关联配置
_cmdProcess = new Process
{
StartInfo = startInfo,
EnableRaisingEvents = true // 允许触发进程事件(如输出数据时)
};
// 启动进程
_cmdProcess.Start();
核心逻辑:
通过 CreateNoWindow = true
隐藏原始 CMD 窗口,同时通过 Redirect...
系列属性将 CMD 的输入输出 "接管" 过来,让程序可以直接与 CMD 交互,而无需显示其默认窗口。
2. 显示 CMD 输出(在自定义界面中)
虽然 CMD 本身的窗口被隐藏了,但代码通过以下方式将其输出显示在自定义的富文本框中:
监听 CMD 的输出事件
// 绑定输出事件:当CMD有正常输出时触发
_cmdProcess.OutputDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
AppendOutput(e.Data); // 显示正常输出
};
// 绑定错误事件:当CMD有错误输出时触发
_cmdProcess.ErrorDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
AppendOutput(e.Data, true); // 显示错误输出(标红)
};
// 开始异步读取输出(必须调用,否则事件不会触发)
_cmdProcess.BeginOutputReadLine();
_cmdProcess.BeginErrorReadLine();
逻辑:
CMD 执行命令后的结果会通过 OutputDataReceived
(正常结果)和 ErrorDataReceived
(错误信息)事件传递给程序,代码通过绑定这两个事件捕获输出内容。
将输出显示到界面控件
private void AppendOutput(string text, bool isError = false)
{
// 跨线程安全检查:如果是后台线程调用,切换到UI线程
if (outputRichTextBox.InvokeRequired)
{
outputRichTextBox.Invoke(new Action<string, bool>(AppendOutput), text, isError);
return;
}
// 设置文本颜色(错误信息标红)
outputRichTextBox.SelectionColor = isError ? Color.Red : outputRichTextBox.ForeColor;
outputRichTextBox.AppendText(text + Environment.NewLine); // 添加到富文本框
outputRichTextBox.ScrollToCaret(); // 自动滚动到最新内容
}
逻辑:
捕获到的 CMD 输出通过 AppendOutput
方法显示在 outputRichTextBox
中,并且用颜色区分正常信息(默认色)和错误信息(红色),实现了 "自定义显示 CMD 内容" 的效果。
总结流程
隐藏启动 CMD:通过 ProcessStartInfo 配置 CreateNoWindow = true 隐藏原始窗口,同时重定向输入输出。
捕获输出:通过 OutputDataReceived 和 ErrorDataReceived 事件监听 CMD 的所有输出。
自定义显示:将捕获的输出通过富文本框展示,并添加颜色区分等增强功能。
核心代码
using System;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace cmdtest
{
public partial class Form1 : Form
{
// 声明进程对象用于控制终端
private Process _cmdProcess;
// 声明控件
private RichTextBox outputRichTextBox;
private TextBox commandTextBox;
private Button sendButton;
public Form1()
{
InitializeComponents(); // 初始化所有控件和事件
InitializeCmdProcess(); // 启动终端进程
}
// 初始化所有控件和事件绑定
private void InitializeComponents()
{
// 配置输出富文本框
outputRichTextBox = new RichTextBox
{
Multiline = true,
ScrollBars = RichTextBoxScrollBars.Vertical,
ReadOnly = true,
Location = new Point(20, 20),
Size = new Size(740, 300),
Text = "终端已启动,等待命令...\r\n"
};
// 配置命令输入框
commandTextBox = new TextBox
{
Location = new Point(20, 340),
Size = new Size(645, 25)
};
commandTextBox.KeyDown += CommandTextBox_KeyDown; // 绑定Enter键事件
// 配置发送按钮
sendButton = new Button
{
Location = new Point(680, 340),
Size = new Size(80, 25),
Text = "发送",
UseVisualStyleBackColor = true
};
sendButton.Click += SendButton_Click; // 绑定点击事件
// 配置窗体
this.ClientSize = new Size(784, 381);
this.Text = "CMD 控制器";
this.FormClosing += Form1_FormClosing; // 绑定窗体关闭事件
// 将控件添加到窗体
this.Controls.Add(outputRichTextBox);
this.Controls.Add(commandTextBox);
this.Controls.Add(sendButton);
}
// 初始化命令行进程
private void InitializeCmdProcess()
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.Default,
StandardErrorEncoding = Encoding.Default
};
_cmdProcess = new Process
{
StartInfo = startInfo,
EnableRaisingEvents = true
};
// 绑定输出事件
_cmdProcess.OutputDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
AppendOutput(e.Data);
};
_cmdProcess.ErrorDataReceived += (s, e) =>
{
if (!string.IsNullOrEmpty(e.Data))
AppendOutput(e.Data, true);
};
// 启动进程
try
{
_cmdProcess.Start();
_cmdProcess.BeginOutputReadLine();
_cmdProcess.BeginErrorReadLine();
}
catch (Exception ex)
{
AppendOutput($"启动终端失败: {ex.Message}", true);
}
}
// 向输出框添加内容(支持颜色区分)
private void AppendOutput(string text, bool isError = false)
{
// 跨线程安全更新UI
if (outputRichTextBox.InvokeRequired)
{
outputRichTextBox.Invoke(new Action<string, bool>(AppendOutput), text, isError);
return;
}
// 设置文本颜色(错误信息为红色)
outputRichTextBox.SelectionColor = isError ? Color.Red : outputRichTextBox.ForeColor;
outputRichTextBox.AppendText(text + Environment.NewLine);
outputRichTextBox.ScrollToCaret(); // 滚动到最新内容
}
// 发送命令按钮点击事件
private void SendButton_Click(object sender, EventArgs e)
{
SendCommand();
}
// 命令输入框按Enter键事件
private void CommandTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
SendCommand();
e.SuppressKeyPress = true; // 阻止系统提示音
}
}
// 发送命令到终端
private void SendCommand()
{
string command = commandTextBox.Text.Trim();
if (string.IsNullOrEmpty(command)) return;
if (_cmdProcess != null && !_cmdProcess.HasExited)
{
try
{
AppendOutput("> " + command); // 显示输入的命令
_cmdProcess.StandardInput.WriteLine(command); // 发送命令
commandTextBox.Clear(); // 清空输入框
}
catch (Exception ex)
{
AppendOutput($"发送命令失败: {ex.Message}", true);
}
}
else
{
AppendOutput("终端已关闭,无法发送命令", true);
}
}
// 窗体关闭事件:清理终端进程
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_cmdProcess != null && !_cmdProcess.HasExited)
{
try
{
_cmdProcess.StandardInput.WriteLine("exit"); // 发送退出命令
_cmdProcess.WaitForExit(1000); // 等待正常退出
if (!_cmdProcess.HasExited)
_cmdProcess.Kill(); // 强制关闭
}
catch { }
finally
{
_cmdProcess.Dispose(); // 释放资源
}
}
}
}
}
123