C#使用Process实现动态执行批处理命令
在 C# 开发中,经常需要调用操作系统原生的命令行工具完成自动化任务,如挂载网络路径、启动服务或清理数据。直接使用 Process 类可以打开 cmd.exe 进程,并通过重定向标准输入和输出流,实现命令的动态注入与结果的实时捕获,从而构建一个稳定的命令行执行管道。
核心功能目标
该方案旨在解决以下操作需求:
- 持续输入:能够在运行过程中,通过输入流写入多条连续的命令。
- 非阻塞输出:利用异步机制读取大数据量的控制台输出,防止主线程被意外卡死。
- 简易 API:开发者只需关注命令字符串的逻辑,无需手动管理复杂的进程句柄释放。
关键配置说明
在使用 ProcessStartInfo 创建子进程时,需确保以下参数设置正确,否则无法实现交互式执行:
UseShellExecute = false:禁用外壳程序执行,允许对标准流进行操作。CreateNoWindow = true:隐藏弹出的控制台黑窗口,保持后端静默运行。RedirectStandardInput/Output/Error = true:必须同时开启,以便接管输入端与接收输出端。
第1步:初始化 Process 实例
进入代码逻辑后,首先实例化 Process,设定文件名为 "cmd.exe"。此时不要直接开始读写流,而是先绑定事件监听器。通过 OutputDataReceived 和 ErrorDataReceived 委托,将输出的每一行数据打印到当前应用的日志控制台中,确保在执行期间能观察到状态反馈。
第2步:启动进程并开始异步读取
调用 pro.Start() 拉起进程。紧接着立即调用 pro.BeginOutputReadLine() 和 pro.BeginErrorReadLine()。这一步是核心,它告诉 .NET 运行时在后台线程独立监控输出缓冲区,一旦有内容产生就触发之前绑定的回调,有效解决了“大数据量输出导致程序阻塞”的问题。
第3步:注入命令并等待退出
获取标准输入流 sIn 并开启 AutoFlush,这样每行写入都会立刻发送给 CMD。随后传入一个委托,在该委托内部依次调用需要执行的命令(如建立网络连接、切换目录等)。最后,务必在结尾加入 p("exit 0")。CMD 只有在收到明确的退出指令后才会关闭进程,进而触发后续的主线程同步等待 pro.WaitForExit(),否则程序会因进程不终止而一直挂起。
完整源码实现
以下是一个健壮的实现版本,包含资源释放的保障。即使中途发生错误或用户强制中断,也能通过 finally 块确保进程不被残留内存中。
using System;
using System.Diagnostics;
/// <summary>
/// 打开控制台执行拼接完成的批处理命令字符串
/// </summary>
/// <param name="inputAction">需要执行的命令委托方法:每次调用
<paramref name="inputAction"/> 中的参数都会执行一次</param>
private static void ExecBatCommand(Action<Action<string>> inputAction)
{
Process pro = null;
StreamWriter sIn = null;
StreamReader sOut = null;
try
{
pro = new Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.UseShellExecute = false;
pro.StartInfo.CreateNoWindow = true;
pro.StartInfo.RedirectStandardInput = true;
pro.StartInfo.RedirectStandardOutput = true;
pro.StartInfo.RedirectStandardError = true;
// 定义输出监听事件
pro.OutputDataReceived += (sender, e) => Console.WriteLine(e.Data);
pro.ErrorDataReceived += (sender, e) => Console.WriteLine(e.Data);
pro.Start();
sIn = pro.StandardInput;
sIn.AutoFlush = true;
// 启动异步读取
pro.BeginOutputReadLine();
pro.BeginErrorReadLine();
// 执行传入的命令序列
inputAction(value => sIn.WriteLine(value));
// 等待 CMD 进程彻底结束
pro.WaitForExit();
}
finally
{
// 安全回收资源的保护性措施
if (pro != null && !pro.HasExited)
pro.Kill();
if (sIn != null)
sIn.Close();
if (sOut != null)
sOut.Close();
if (pro != null)
pro.Close();
}
}
使用示例与注意事项
在实际业务场景中,您可以利用此方法批量执行维护脚本。例如,向指定服务器推送配置或挂载共享文件夹:
ExecBatCommand(p =>
{
// 模拟挂载远程共享目录并赋予权限
p(@"net use \\10.32.11.21\ERPProject yintai@123 /user:yt\ERPDeployer");
// 中间可以插入更多逻辑,比如 ping 测试、拷贝文件等...
// 【至关重要】必须在最后一步通知 CMD 退出,防止进程悬空
p("exit 0");
});
请注意:exit 0 必须是序列中的最后一个操作。若在其后追加命令,由于 CMD 已经准备退出,新发送的数据可能会抛出异常或被丢弃,从而导致程序不可预期的报错行为。
以上就是 C# 利用 Process 实现动态执行批处理命令的详细过程,更多关于 C# 系统底层交互的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









