根据 MSDN,我真的感觉自己在遵循最佳实践.但我很可能遗漏了一些东西,因为我的代码在从这一行继续后挂起:string errorOutput = cmd.StandardError.ReadToEnd();
。我做错了什么?
var batchfile = File.OpenWrite("run.bat");
StreamWriter writer = new StreamWriter(batchfile);
writer.Write("dotnet run" + '\n');
//writer.Write("set /p temp=\"Hit enter to continue\"" + '\n');
writer.Close();
var cmd = new Process();
cmd.StartInfo.FileName = batchfile.Name;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardError = true;
cmd.Start();
string errorOutput = cmd.StandardError.ReadToEnd();
cmd.WaitForExit();
var outputfile = File.OpenWrite("run_errorOut.txt");
StreamWriter outputWriter = new StreamWriter(outputfile);
outputWriter.Write(errorOutput);
outputWriter.Close();
如果有帮助:目前这段代码正在 dotnetcore2.2 应用程序(其目标框架是“netcoreapp2.2”)的 xunit 测试中运行。
最佳答案
所以不久前我遇到了一个非常相似的问题,几乎完全一样,我发现的是:
- 尝试在没有任何可读 block 的情况下读取 StandardError/Output block ,直到有可读的东西为止(如果没有任何内容可读则死锁 - 例如进程已退出)
cmd.HasExited
在读取 StandardError/Output 之前为 false,因此无法用于检测何时完成(然后读取 StandardError/Output)
我发现最可靠的方法是在 Process
上使用提供的事件:
var outData = new StringBuilder();
var errData = new StringBuilder();
cmd.OutputDataReceived += (sender, args) => outData.Append(args.Data ?? string.Empty);
cmd.ErrorDataReceived += (sender, args) => errData.Append(args.Data ?? string.Empty);
然后在 cmd.Start() == true
之后:
cmd.BeginErrorReadLine();
cmd.BeginOutputReadLine();
开始触发事件。
进程退出后,您可以在 StringBuilder 上调用 .ToString()
来获取数据:
Console.WriteLine(outData.ToString());
Console.WriteLine(errData.ToString());
(注意 .ToString()
在使用 Console.WriteLine
时可以是隐式的)
关于c# - 如何在没有死锁的情况下正确读取 c# 进程标准错误流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56571693/