Liero
Liero

Reputation: 27328

Process won't exit when UseShellExecute = false, but exits when UseShellExecute = true

I run a process from a asp.net core application:

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

When createShell is true, the process writes some PDF file and exits. When I set it to false, it runs with the same StandardOutput and StandardError it seems, but never finishes and the PDF file is empty.

Why does the process hang when there is no console window visible?

Upvotes: 0

Views: 1011

Answers (1)

vernou
vernou

Reputation: 7590

When ProcessStartInfo.RedirectStandardOutput is true, the process's output is redirected to Process.StandardOutput.

But in the OP code the Process.StandardOutput isn't read and the buffer fills up to its limit. When the limit is reached, the process can't write Process.StandardOutput and wait some free space.

Same story with ProcessStartInfo.RedirectStandardError and Process.StandardError

One solution is to set ProcessStartInfo.RedirectStandardOutput and ProcessStartInfo.RedirectStandardError to false.

Other solution if you want the output, you can redirect the output to other stream. See this example where the output is redirected to a file :

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

Upvotes: 0

Related Questions