C#基础(③CMD进程)
在 C# 中,打开和显示 CMD 进程主要通过 System.Diagnostics.Process
类实现,核心是配置进程启动信息并处理其输入输出。以下结合代码细节说明具体实现方式:
1. 启动 CMD 进程(隐藏原始窗口)
代码通过 ProcessStartInfo
配置 CMD 进程的启动参数,关键是隐藏原始 CMD 窗口并重定向输入输出:
// 配置进程启动信息
ProcessStartInfo startInfo = new ProcessStartInfo
{FileName = "cmd.exe", // 指定要启动的程序为CMDUseShellExecute = 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){// 跨线程安全更新UIif (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