我有一个程序(服务器),它向控制台输出四行输出,然后开始侦听来自客户端程序的传入连接。
我有另一个程序(测试人员),我想从服务器读取标准输出并进行分析。我已经设置了测试程序以启动服务器并获得其输出如下:
Process server = new Process();
server.StartInfo.FileName = "server.exe";
server.StartInfo.UseShellExecute = false;
server.StartInfo.RedirectStandardInput = true;
server.StartInfo.RedirectStandardOutput = true;
server.StartInfo.RedirectStandardError = true;
server.Start();
StreamReader serverOutput = server.StandardOutput;
string line = serverOutput.ReadToEnd();
...
我遇到的问题是,当我自己执行服务器时(或者当我使用没有重定向输出的测试仪执行它时)我可以在控制台上看到所有四行。但是,当我使用上面的代码将服务器输出重定向到测试程序时,测试程序挂起“ReadToEnd”命令,好像它正在等待来自服务器的更多输出。
我还尝试使用“ReadLine”命令并将其放入FOR循环中,重复4次。当我这样做时,前三行输出成功获取,然后它挂起在第4个“ReadLine”上,从不检索第4行服务器输出。
最后,我还尝试使用“读取”命令尝试一次获取一个字符,但仍然无法从第4行服务器输出中获取任何字符。
有关我在这里缺少什么的建议吗?
更新
经过大量的搜索,我终于确定问题与输出缓冲问题有关。服务器程序(用C ++编写)写入cout
,在打印到屏幕时似乎会自动刷新,但在将stdout重定向到测试程序时不会自动刷新。我可以将setvbuf(stdout, NULL, _IONBF, 0);
添加到服务器程序中以使stdout不被缓冲,但我更愿意找到另一个不涉及更改服务器程序的解决方案。
答案 0 :(得分:1)
当流结束时,ReadToEnd将返回。当程序关闭时会发生这种情况。
您可以尝试使用事件处理程序server.OutputDataReceived
读取数据。这样你就可以异步接收它,而不会阻止你的程序。
答案 1 :(得分:0)
昨天我在尝试解决这个问题时发现了这个问题,所以我想我会用我找到的解决方案回答这个问题,只是为了后人。
我遇到的问题是process.WaitForExit
调用是在完成读取之前关闭输出流。通过在调用ReadLine
之前运行几个Task
和Wait
中的WaitForExit
循环,我设法获得所有输出(来自Git调用,在这个例子中)。
希望这有助于某人。
var psi = new ProcessStartInfo(@"C:\Program Files (x86)\Git\bin\git.exe", "push " + remoteUrl + " " + branch)
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var process = new Process
{
StartInfo = psi
};
Console.WriteLine("Pushing...");
process.Start();
var stdOutTask = Task.Factory.StartNew(() =>
{
string str;
while ((str = process.StandardOutput.ReadLine()) != null)
{
Console.WriteLine(str);
}
});
var stdErrorTask = Task.Factory.StartNew(() =>
{
string str;
while ((str = process.StandardError.ReadLine()) != null)
{
Console.WriteLine(str);
}
});
stdOutTask.Wait();
stdErrorTask.Wait();
process.WaitForExit();
process.Close();