我通过c#Diagnostics.Process类调用exe并从它的StdOut读取输出。如果它在指定的时间内没有自动终止,则强制终止该过程,例如:
process.StartInfo.FileName = @"D:\t.exe";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = false;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;
process.WaitForExit(500);
if (!process.HasExited)
{
process.Kill();
process.WaitForExit();
}
string stdOutContents = process.StandardOutput.ReadToEnd();
现在问题是当exe正常终止时,代码会成功运行。但是如果它无法正常终止(通常exe会陷入某个无限循环),stdOutContents将被读作空字符串。
如何在进程被终止后读取StdOut(不使用process.OutputDataReceived事件技术)? (已经证实,exe-in-question确实会将某些内容写入StdOut,即使它被卡在某处)。
更新1
有关正在调用的Exe的详细信息(在此问题中称为“本机应用”)
它是一个用c语言实现的小工具,使用MS C ++编译器编译。它在将状态信息输出到StdOut(使用putchar
)时完成其工作。
只有两种可能的操作情况:
已使用cmd验证了这两种方案。
有关新尝试的详细信息
我写了一个c#app(称为虚拟应用程序),模仿本机应用程序行为,这段代码工作正常。但是,当为本机应用程序运行时,我什么都得不到。
我不明白为什么代码无法读取原生应用程序输出的内容?
我也尝试使用OutputDataReceived
的事件处理程序。当代码试图终止进程时,它只被args.Data = null调用一次。检查虚拟应用程序的行为表明,当调用process.kill时,将使用args.Data = null调用该处理程序。因此,这似乎是两种应用程序的标准行为。
我也尝试更改原生应用的换行符。由于它是用c语言实现的,因此它使用\ n作为换行符。我尝试将\ r \ n对用于换行,但StdOut仍为空白(对于案例2)。
答案 0 :(得分:0)
我有同样的讯问而doc of Process.Kill说
如果您致电Kill,则由流程编辑的数据或分配给流程的资源可能会丢失。
这似乎表明您不能依赖于读取进程的StandardOutput,尽管没有明确说明输出/错误流已被处理。
我终于受到了这个答案的启发 How to spawn a process and capture its STDOUT in .NET?
我使用以下代码:
var info = new ProcessStartInfo("some.exe");
info.CreateNoWindow = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
using (var p = new Process())
{
p.StartInfo = info;
var output = new StringBuilder();
p.OutputDataReceived += (sender, eventArgs) =>
{
output.AppendLine(eventArgs.Data);
};
p.Start();
p.BeginOutputReadLine();
if (!p.WaitForExit(5000))
{
Console.WriteLine("Taking too long...");
p.Kill();
Console.WriteLine("Process killed, output :\n" + output);
}
}
相同的模式可以与 ErrorDataReceived
一起使用请注意,可能会错过子进程的某些未刷新的输出,但是在我的情况下,我不希望从需要被杀死的进程中获取太多内容,最多用于调试目的的一些信息。