首页 > 解决方案 > UseShellExecute = false 时进程不会退出,但 UseShellExecute = true 时退出

问题描述

我从 asp.net 核心应用程序运行一个进程:

bool createShell = true;
//generate output pdf
using var pdfGeneratorProcess = new System.Diagnostics.Process
{
    StartInfo = new ProcessStartInfo
    {
        UseShellExecute = createShell,
        CreateNoWindow = createShell,
        RedirectStandardError = !createShell,
        RedirectStandardOutput = !createShell,
        WorkingDirectory = dir,
        FileName = "java",
        Arguments = $"-cp \"fop-2.0.jar;lib/*\"; FOPLocalPDFGenerator {rendererFile} {inputFile} {outputFile}"
    }
};
_logger.LogInformation("{CMD}", $"{pdfGeneratorProcess.StartInfo.FileName} {pdfGeneratorProcess.StartInfo.Arguments}");
pdfGeneratorProcess.Start();

当 createShell 为真时,进程写入一些 PDF 文件并退出。当我将其设置为 false 时,它​​会以相同的 StandardOutput 和 StandardError 运行,但从未完成并且 PDF 文件为空。

当没有可见的控制台窗口时,为什么进程会挂起?

标签: c#asp.net-core.net-core.net-5

解决方案


ProcessStartInfo.RedirectStandardOutput为真时,进程的输出被重定向到Process.StandardOutput

但是在 OP 代码Process.StandardOutput中没有读取并且缓冲区填满了它的限制。达到限制时,进程无法写入Process.StandardOutput并等待一些可用空间。

ProcessStartInfo.RedirectStandardErrorProcess.StandardError的故事相同

一种解决方案是设置ProcessStartInfo.RedirectStandardOutputProcessStartInfo.RedirectStandardError为假。

如果您想要输出其他解决方案,您可以将输出重定向到其他流。请参阅此示例,其中将输出重定向到文件:

void Redirect(StreamReader output, StreamWriter to)
{
    string textLine;
    while ((textLine = output.ReadLine()) != null)
    {
        to.WriteLine(textLine);
    }
}

bool createShell = true;
//generate output pdf
using var pdfGeneratorProcess = new System.Diagnostics.Process {
    StartInfo = new ProcessStartInfo {
        UseShellExecute = createShell,
        CreateNoWindow = !createShell, // I inversed the condition
        RedirectStandardError = !createShell,
        RedirectStandardOutput = !createShell,
        WorkingDirectory = dir,
        FileName = "java",
        Arguments = $"-cp \"fop-2.0.jar;lib/*\"; FOPLocalPDFGenerator {rendererFile} {inputFile} {outputFile}"
    }
};
_logger.LogInformation("{CMD}", $"{pdfGeneratorProcess.StartInfo.FileName} {pdfGeneratorProcess.StartInfo.Arguments}");
pdfGeneratorProcess.Start();

using (StreamWriter writer = File.CreateText(@"C:\Temp\log.txt"))
{
    var standardOutputThread = new Thread(new ThreadStart(() => Redirect(pdfGeneratorProcess.StandardOutput, writer)));
    var errorOutputThread = new Thread(new ThreadStart(() => Redirect(pdfGeneratorProcess.StandardError, writer)));
    standardOutputThread.Start();
    errorOutputThread.Start();
    standardOutputThread.Join();
    errorOutputThread.Join();
}

pdfGeneratorProcess.WaitForExit();

推荐阅读