遗留程序“LegacyBuilder”运行“batch.cmd”文件,然后将其输出重定向到文件,如下所示。
ProcessStartInfo processStartInfo = new ProcessStartInfo("C:\\batch.cmd");
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.UseShellExecute = false;
using (Process process = Process.Start(processStartInfo))
{
using (StreamWriter logWriter = new StreamWriter("C:\\log.txt"))
{
while ((logLine = process.StandardOutput.ReadLine()) != null)
{
logWriter.WriteLine(logLine);
}
}
}
batch.cmd 包含这一行
C:\SomeApp.exe "arg1" "arg2" "arg3"
SomeApp.exe 正在使用来自不同程序集的以下方法。
SomeAssembly.SomeClass.GenerateOutput()
此 GenerateOutput 方法为第 3 方控制台程序创建一个进程。在遇到缓冲区死锁问题后,我发现(我认为来自另一个 SO 问题)以下代码永远不会导致这种死锁,并且“LegacyBuilder”捕获了第 3 方程序的输出。
Console.Write("I'm creating the process!");
ProcessStartInfo processStartInfo = new ProcessStartInfo("C:\\3rdPartyConsoleExe.exe");
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.UseShellExecute = false;
using (Process process = new Process())
{
process.StartInfo = processStartInfo;
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
process.OutputDataReceived += (sender, e) =>
{
if (e.Data == null) outputWaitHandle.Set();
else output.AppendLine(e.Data);
};
process.ErrorDataReceived += (sender, e) =>
{
if (e.Data == null) errorWaitHandle.Set();
else error.AppendLine(e.Data);
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (process.WaitForExit(60000) && outputWaitHandle.WaitOne(60000) && errorWaitHandle.WaitOne(60000))
{
Console.WriteLine(output.ToString());
Console.WriteLine(error.ToString());
if (process.ExitCode > 0)
Console.WriteLine("PROCESS COMPLETED ExitCode=" + process.ExitCode.ToString());
}
else
Console.WriteLine("PROCESS TIMED OUT");
}
}
请注意 Console.Write("我正在创建进程!");
到目前为止一切顺利,一切正常,所有输出都被“LegacyBuilder”捕获
现在,通过调用 powershell 脚本更新了 batch.cmd。
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\PowerShell.exe -File "C:\powershellscript.ps1"
powershell 脚本基本上是加载 SomeAssembly,创建 SomeObject 然后调用 GenerateOutput 方法。像这样。
Add-Type -Path "C:\SomeAssembly.dll";
$someCls = New-Object SomeAssembly.SomeClass()
$someCls.GenerateOutput();
问题:文本“我正在创建流程!” 正在被“LegacyBuilder”捕获,所以这将是标准输出。
但是 GenerateOutput() 方法的预期输出没有产生任何东西,并且在几次尝试调用后它再次陷入僵局。甚至没有调用“过程超时”。
这很奇怪。
batch.cmd 调用“SomeApp.exe”,后者调用 SomeAssembly.SomeClass.GenerateOutput()。文件中存在第 3 方程序的输出,并且 batch.cmd 成功继续。
batch.cmd 调用 powershell 来加载创建 SomeAssembly.SomeClass 对象的脚本,然后调用 GenerateOutput() 方法。输出不存在,只有直接 Console.Write 调用的输出是......经过几次尝试,它会死锁并且 batch.cmd 永远不会继续。
有什么帮助吗?我希望存在像“StopBufferDeadlocksInPowershell -includeStupidLegacyNestedProcessCalls”这样的东西......
编辑 1
我很想避免在“LegacyBuilder”中进行任何更改,因为其中的代码非常非常复杂(最上面的代码示例只是简化了),虽然我很想完全重写它,但这会非常耗时。