c# - 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 文件为空。
当没有可见的控制台窗口时,为什么进程会挂起?
解决方案
当ProcessStartInfo.RedirectStandardOutput为真时,进程的输出被重定向到Process.StandardOutput。
但是在 OP 代码Process.StandardOutput
中没有读取并且缓冲区填满了它的限制。达到限制时,进程无法写入Process.StandardOutput
并等待一些可用空间。
ProcessStartInfo.RedirectStandardError和Process.StandardError的故事相同
一种解决方案是设置ProcessStartInfo.RedirectStandardOutput
和ProcessStartInfo.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();
推荐阅读
- sql-server - Microsoft SQL Server 只需要查询中的最高结果
- android - 如何在android上将保存的位图作为文件访问?
- r - 如何匹配多个结尾字符?
- json - REST (JSON) - 检查日期是否在两个日期之间
- ios - Fastlane 不断警告我正在使用 Ruby 2.2.4
- r - eval 中的错误(predvars、data、env):“closure”类型的“envir”参数无效
- python - pandas 字符串操作:根据其他列内容动态选择列
- javascript - 有没有办法动态创建 feTurbulence 过滤器?
- javascript - 尽管编码正确,为什么我的 JS 不工作?
- r - 具有复杂调查设计的 R 和 Sudaan 之间的不同结果