我需要运行一些外部exe,并读取其输出和错误。
prc = new Process();
prc.StartInfo.UseShellExecute = false;
prc.StartInfo.FileName = fileName;
prc.StartInfo.Arguments = arguments;
prc.StartInfo.LoadUserProfile = true;
prc.StartInfo.RedirectStandardOutput = true;
prc.StartInfo.RedirectStandardError = true;
prc.OutputDataReceived += (sendingProcess, outLine) => outputText.AppendLine(outLine.Data);
prc.ErrorDataReceived += (sendingProcess, errorLine) => errorText.AppendLine(errorLine.Data);
prc.Start();
prc.BeginOutputReadLine();
prc.BeginErrorReadLine();
发生这种情况的线程可能会随时中止,我无法对其进行任何更改,因此我无法使用prc.WaitForExit();
因为它无法中止,直到进程本身被杀死。
这意味着每次线程中止时,所有执行都会挂断。
所以我用另外的方法替换它:
while (!Thread.CurrentThread.ThreadState.HasFlag(ThreadState.AbortRequested) && !Thread.CurrentThread.ThreadState.HasFlag(ThreadState.Aborted))
{
if (!process.HasExited) continue;
return process.ExitCode;
}
唯一的问题是输出。奇怪的是,有时候输出和错误都会丢失字符串,添加Thread.Sleep
可以解决这个问题,这意味着异步写入由于某种原因无法保持。
这似乎是一个微不足道的问题,但我无法找到可靠的解决方案。 Thread.Sleep
不是一个好习惯,执行时间非常重要。可靠地获取所有错误和输出的最佳方法是什么?
答案 0 :(得分:1)
输出的问题是,用于将其传递到进程的匿名管道的写入结束可能不会被刷新,直到进程退出 - 它并不总是发生,但是你不能依赖它不正在发生。相反,为什么不在一个单独的线程中运行进程内容,包括WaitForExit()
(或者只是WaitForExit()
)?您的原始帖子可以等待此工作人员以Thread.Abort
方式完成(例如Thread.Join()
),您将获得完整的输出。或者,如果您不担心ThreadAbortException
但需要能够取消WaitForExit()
来电,则可以使用WaitHandle.WaitAny(prc.Handle,cancellationToken.WaitHandle)
。