C#基础(③CMD进程)

发布于:2025-09-01 ⋅ 阅读:(22) ⋅ 点赞:(0)

在 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


网站公告

今日签到

点亮在社区的每一天
去签到