【问题标题】:Process.Start random stops during the middle of the executionProcess.Start 在执行过程中随机停止
【发布时间】:2015-07-28 20:47:23
【问题描述】:

我需要调用外部程序将电子邮件下载到文件夹中。这个外部程序是用 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 应用程序会在不应该的地方停止,例如在两次 Log 调用之间:

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);
}

它打印“From....”并停止,如果我终止 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();

【问题讨论】:

    标签: c# process redirectstandardoutput


    【解决方案1】:

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

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

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

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

    这就像我在过去一周左右第三次看到完全相同的错误 sn-p。你从哪里得到那些明显错误的代码示例? :D

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

    p.Start();
    
    var output = p.ReadToEnd();
    

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

    【讨论】:

      猜你喜欢
      • 2018-07-03
      • 2022-08-18
      • 2021-08-26
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      相关资源
      最近更新 更多