Process.Start在执行过程中随机停止

时间:2015-07-28 12:25:55

标签: c# process redirectstandardoutput

我需要调用外部程序将电子邮件下载到文件夹中。这个外部程序是用Excelsior JET(Jar to Exe)编译的Java

这就是我打电话的方式:

var process = new Process
{
    StartInfo =
    {
        Arguments = Arguments(folder),
        FileName = Path.Combine(@"C:/Fakepath"), "GetMail.exe"),
        CreateNoWindow = true,
        UseShellExecute = false,
        RedirectStandardError = true,
        RedirectStandardOutput = true
    }
};

process.Start();
process.WaitForExit();

var output = process.StandardOutput.ReadToEnd();
var outputError = process.StandardError.ReadToEnd();

//if (!String.IsNullOrEmpty(output))
//    LogWriter.Log("GetMail", output.Trim());

if (!String.IsNullOrEmpty(outputError))
      LogWriter.Log("GetMail Erro", outputError.Trim());

process.Close();

我猜输出有问题,例如this other thread here

Java应用停止在两个日志调用之间的位置:

try
{
    for (Address addr : msg.getFrom())
    {
        AppConfig.getLogControl().WriteLog("\tFrom.............:" + addr);
    }
} catch (Exception e) { }

MimeMessage msgMIME = null;

try
{
    AppConfig.getLogControl().WriteLog("\tTesting message type... ");
    msg.isMimeType("text/*");
    AppConfig.getLogControl().WriteLog("\t\tMultipart type");
} catch (MessagingException ex)
{
    AppConfig.getLogControl().WriteLog("\t\tMIME type");
    AppConfig.getLogControl().WriteLog("\tDownloading data... ");
    msgMIME = TrataMimeMessage(msg);
}

它打印“从......”并停止,如果我终止C#进程,Java应用程序将继续打印其余部分。

修改

reading this page之后,我想我知道我做错了什么。 MSDN页面的其中一个部分:

 // To avoid deadlocks, always read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

1 个答案:

答案 0 :(得分:2)

通常情况下,您无需读取输出/错误流即可重定向。当目标应用程序填充其自己的输出缓冲区时,它会在尝试向输出写入更多内容时挂起。

您需要始终阅读流。例如,

var outputTask = p.StandardOutput.ReadToEndAsync();
var errorTask = p.StandardError.ReadToEndAsync();

var output = await outputTask;
var error = await errorTask;

也不需要WaitForExit - 这是ReadToEnd的用途。虽然我确实倾向于使用它 - 但它必须在你开始阅读输出后,否则你注定要失败。

这就像我在上周左右第三次看到完全相同的错误片段。你在哪里得到那些公然错误的代码样本? :D

如果你不能使用await,这实际上有点棘手。处理此问题的最简单方法是停止重定向错误流(它并不是所有使用得很好)并且仅重定向标准输出。然后你可以简单地做

p.Start();

var output = p.ReadToEnd();

注意缺少WaitForExit - 你必须读取流,否则你就会死锁。该进程尝试写入输出,但其输出缓冲区已满。您只在进程退出后才开始读取输出,但在读取输出之前无法退出。同样,WaitForExit很好,但在 ReadToEnd之后使用