Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
219 views
in Technique[技术] by (71.8m points)

c# - 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?

question from:https://stackoverflow.com/questions/66059598/process-wont-exit-when-useshellexecute-false-but-exits-when-useshellexecute

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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:Templog.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();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...