Quelle peut être la raison du blocage de mon processus en attendant la sortie?
Ce code doit démarrer le script powershell qui, à l'intérieur, effectue de nombreuses actions, par exemple commencer à recompiler le code via MSBuild, mais le problème est probablement qu'il génère trop de sortie et ce code se bloque en attendant de quitter même après l'exécution correcte du script Power Shell.
c'est un peu "bizarre" parce que parfois ce code fonctionne bien et parfois il reste bloqué.
Le code se bloque à:
process.WaitForExit (ProcessTimeOutMiliseconds);
Le script Powershell s'exécute en 1 à 2 secondes, tandis que le délai d'expiration est de 19 secondes.
public static (bool Success, string Logs) ExecuteScript(string path, int ProcessTimeOutMiliseconds, params string[] args)
{
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
using (var outputWaitHandle = new AutoResetEvent(false))
using (var errorWaitHandle = new AutoResetEvent(false))
{
try
{
using (var process = new Process())
{
process.StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "powershell.exe",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
Arguments = $"-ExecutionPolicy Bypass -File \"{path}\"",
WorkingDirectory = Path.GetDirectoryName(path)
};
if (args.Length > 0)
{
var arguments = string.Join(" ", args.Select(x => $"\"{x}\""));
process.StartInfo.Arguments += $" {arguments}";
}
output.AppendLine($"args:'{process.StartInfo.Arguments}'");
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();
process.WaitForExit(ProcessTimeOutMiliseconds);
var logs = output + Environment.NewLine + error;
return process.ExitCode == 0 ? (true, logs) : (false, logs);
}
}
finally
{
outputWaitHandle.WaitOne(ProcessTimeOutMiliseconds);
errorWaitHandle.WaitOne(ProcessTimeOutMiliseconds);
}
}
}
Scénario:
start-process $args[0] App.csproj -Wait -NoNewWindow
[string]$sourceDirectory = "\bin\Debug\*"
[int]$count = (dir $sourceDirectory | measure).Count;
If ($count -eq 0)
{
exit 1;
}
Else
{
exit 0;
}
où
$args[0] = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin\MSBuild.exe"
Éditer
À la solution de @ ingen, j'ai ajouté un petit wrapper qui réessaye d'exécuter le MS Build raccroché
public static void ExecuteScriptRx(string path, int processTimeOutMilliseconds, out string logs, out bool success, params string[] args)
{
var current = 0;
int attempts_count = 5;
bool _local_success = false;
string _local_logs = "";
while (attempts_count > 0 && _local_success == false)
{
Console.WriteLine($"Attempt: {++current}");
InternalExecuteScript(path, processTimeOutMilliseconds, out _local_logs, out _local_success, args);
attempts_count--;
}
success = _local_success;
logs = _local_logs;
}
Où InternalExecuteScriptest le code d'Ingen
Rxapproche a fonctionné (car elle n'a pas dépassé le délai d'expiration) même avec un processus MSBuild errant qui mène à une attente indéfinie? intéressé à savoir comment cela a été géré