【问题标题】:Process won't exit when UseShellExecute = false, but exits when UseShellExecute = trueUseShellExecute = false 时进程不会退出,但 UseShellExecute = true 时退出
【发布时间】:2023-11-23 00:42:01
【问题描述】:

我从一个 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 文件为空。

为什么看不到控制台窗口时进程挂起?

【问题讨论】:

  • CreateNoWindow = !createShell?

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


【解决方案1】:

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

但在 OP 代码中,Process.StandardOutput 未被读取,缓冲区已满。当达到限制时,进程无法写入Process.StandardOutput 并等待一些空闲空间。

ProcessStartInfo.RedirectStandardErrorProcess.StandardError 也是如此

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

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

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

【讨论】: