C# 执行 Postman 的 Newman 命令时进程挂起无响应问题求助
C#调用cmd执行Newman命令卡住的解决方法
问题根源
当前代码开启了RedirectStandardError = true但没有消费标准错误流的内容,当Newman输出的日志/错误内容填满错误流缓冲区后,系统会挂起Newman进程等待缓冲区被读取,就会出现永久卡住的现象。
可行解决步骤
- 方案1:不需要捕获Newman输出时,直接关闭所有不需要的重定向
你当前使用cmd /C参数执行命令,cmd执行完指定命令后会自动退出,不需要额外重定向标准输入写exit指令,直接关闭所有重定向即可避免缓冲区死锁。
优化参考代码:string cmdCommand = "newman run demo.postman_collection.json --env-var HTTP_PROXY --insecure"; int TotalTimeout = 150000; using System.Diagnostics.Process CliProcess = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); if (_inputDir != null) { startInfo.WorkingDirectory = _inputDir; } startInfo.CreateNoWindow = true; startInfo.FileName = "cmd.exe"; startInfo.Arguments = "/C " + cmdCommand; startInfo.UseShellExecute = false; // 关闭所有不需要的重定向 startInfo.RedirectStandardError = false; startInfo.RedirectStandardOutput = false; startInfo.RedirectStandardInput = false; CliProcess.StartInfo = startInfo; CliProcess.Start(); bool processExited = CliProcess.WaitForExit(TotalTimeout); if (!processExited) { // 优先温和关闭,失败再强杀 if (!CliProcess.CloseMainWindow()) { CliProcess.Kill(); } CliProcess.WaitForExit(); TraceLogger.Instance.LogMessage(TraceLevel.Warning, MsgSrc, "[SendCmdCommand(string cmdCommand)] Newman process was killed due to timeout"); } - 方案2:需要捕获Newman输出时,异步消费所有重定向的流
如果需要收集Newman的执行日志,必须同时异步读取标准输出和标准错误流,避免任意一个缓冲区被填满导致死锁。
优化参考代码:string cmdCommand = "newman run demo.postman_collection.json --env-var HTTP_PROXY --insecure"; int TotalTimeout = 150000; using System.Diagnostics.Process CliProcess = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); if (_inputDir != null) { startInfo.WorkingDirectory = _inputDir; } startInfo.CreateNoWindow = true; startInfo.FileName = "cmd.exe"; startInfo.Arguments = "/C " + cmdCommand; startInfo.UseShellExecute = false; // 开启输出和错误流重定向 startInfo.RedirectStandardError = true; startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardInput = false; // 绑定异步接收事件 CliProcess.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { // 自行处理正常输出日志 TraceLogger.Instance.LogMessage(TraceLevel.Info, MsgSrc, e.Data); } }; CliProcess.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { // 自行处理错误输出日志 TraceLogger.Instance.LogMessage(TraceLevel.Error, MsgSrc, e.Data); } }; CliProcess.StartInfo = startInfo; CliProcess.Start(); // 启动异步读取 CliProcess.BeginOutputReadLine(); CliProcess.BeginErrorReadLine(); bool processExited = CliProcess.WaitForExit(TotalTimeout); // 等待所有异步读取操作完成 CliProcess.WaitForExit(); if (!processExited) { if (!CliProcess.CloseMainWindow()) { CliProcess.Kill(); } CliProcess.WaitForExit(); TraceLogger.Instance.LogMessage(TraceLevel.Warning, MsgSrc, "[SendCmdCommand(string cmdCommand)] Newman process was killed due to timeout"); }
额外排查点
- 先在你配置的
WorkingDirectory路径下手动执行Newman命令,确认可以正常跑完,没有交互式提示(比如需要输入认证信息、确认操作等) - 可以给Newman命令添加
--silent参数减少非必要输出,降低缓冲区溢出概率 - 确认程序执行身份有集合JSON文件的读取权限,以及访问目标接口的网络权限
内容的提问来源于stack exchange,提问作者Aviad
相关产品推荐
相关产品推荐

