关于执行外部进程

About executing external processes

我需要一些外部 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 几乎不是一个好习惯,执行时间非常重要。可靠地获取所有错误和输出的最佳方法是什么?

输出的问题是用于将它传送到您的进程的匿名管道的写入端可能不会被刷新,直到进程退出 - 它并不总是发生,但您不能依赖它没有发生。相反,为什么不 运行 进程内容,包括 WaitForExit()(或者可能只是 WaitForExit())在一个单独的线程中?您的原始线程可以等待该工作人员以 Thread.Abort 可行的方式(例如 Thread.Join())完成,您将获得完整的输出。或者,如果您不担心 ThreadAbortException 但需要能够取消 WaitForExit() 调用,您可以使用 WaitHandle.WaitAny(prc.Handle,cancellationToken.WaitHandle).