C#调用cmd执行bat后无法读取已存在cmd进程的标准输出怎么办
报错原因
- 核心原因1:你在cmd参数中用了
start /MIN命令,这个cmd内置命令会启动一个独立的新cmd进程运行bat脚本,你配置了重定向输出的原cmd进程执行完start命令就退出了,后续你获取到的pid是新启动的bat进程的pid,这个新进程没有配置过输出重定向,不允许读取StandardOutput。 - 核心原因2:通过
Process.GetProcessById()获取的进程实例,就算目标进程启动时配置了重定向,也无法获取到输出流上下文,只有你自己调用Start()启动的那个Process实例,才能读取到对应进程的重定向输出。 - 补充遗漏点:你现有代码没有设置
batFile.UseShellExecute = false,这是重定向输出的必填配置,未设置的话重定向也不会生效。
解决方法
方案1:移除start命令直接启动bat(推荐)
不需要用cmd的start命令开新进程,直接让你创建的Process实例运行bat,配置窗口隐藏属性即可满足后台运行的需求,同时直接存储Process实例而非仅pid,方便后续读输出。
正确代码示例:
static List<Process> emulatorProcessList = new List<Process>(); // 启动bat逻辑 ProcessStartInfo batFile = new ProcessStartInfo("cmd.exe", String.Format("/C {0}.bat ", numEmulator)); batFile.WindowStyle = ProcessWindowStyle.Hidden; batFile.CreateNoWindow = true; batFile.RedirectStandardOutput = true; batFile.RedirectStandardError = true; batFile.UseShellExecute = false; // 重定向输出必填配置 Process launchBat = new Process(); launchBat.StartInfo = batFile; launchBat.Start(); emulatorProcessList.Add(launchBat); // 直接存储Process实例,不要只存pid // 后续读取输出逻辑 foreach (var procEm in emulatorProcessList) { if (!procEm.HasExited) { Console.WriteLine(procEm.StandardOutput.ReadLine()); } }
方案2:确需多开独立进程的处理
如果业务必须要每个bat都是独立进程,不要通过cmd的start命令启动,而是循环为每个bat单独创建Process实例,每个实例都配置重定向输出属性,统一存到Process列表中后续读取输出即可。
内容的提问来源于stack exchange,提问作者Rustamom
相关产品推荐
相关产品推荐

