27 votes

Comment obtenir la sortie d'un processus System.Diagnostics.Process ?

Je lance ffmpeg comme ça :

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.Start();
p.WaitForExit();

... mais le problème est que la console avec ffmpeg s'affiche et disparaît aussitôt, ce qui fait que je ne peux pas avoir de retour. Je ne sais même pas si le processus s'est déroulé correctement.

Alors comment puis-je, soit :

  • Dites à la console de rester ouverte

  • Récupérer dans le C# ce que la console a affiché

44voto

Lucas Jones Points 11741

Ce que vous devez faire, c'est capturer le flux de sortie standard :

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
string q = "";
while ( ! p.HasExited ) {
    q += p.StandardOutput.ReadToEnd();
}

Vous devrez peut-être aussi faire quelque chose de similaire avec StandardError . Vous pouvez ensuite faire ce que vous voulez avec q .

C'est un peu délicat, comme je l'ai découvert en une de mes questions

Comme Jon Skeet l'a fait remarquer, il n'est pas judicieux, du point de vue des performances, d'utiliser la concaténation de chaînes de caractères de cette manière. StringBuilder :

p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
// instead of p.WaitForExit(), do
StringBuilder q = new StringBuilder();
while ( ! p.HasExited ) {
    q.Append(p.StandardOutput.ReadToEnd());
}
string r = q.ToString();

15voto

chiccodoro Points 5881

La réponse de Lucas a une condition de course : Si le processus se termine rapidement, la boucle while peut ne jamais être entrée. Dans ce cas, la sortie n'est jamais lue, même si elle contient des données.

J'ai essayé ce qui suit et cela fonctionne très bien :

using (var process = Process.Start(startInfo))
{
    process.WaitForExit();

    var output = process.StandardOutput.ReadToEnd();
    // ...
}

La différence avec la réponse de Lucas est que vous n'obtenez la sortie qu'après avoir attendu que le processus se termine. Les deux approches peuvent être combinées :

using (var process = Process.Start(startInfo))
{
    var standardOutput = new StringBuilder();

    while (!process.HasExited)
    {
        standardOutput.Append(process.StandardOutput.ReadToEnd());
    }

    process.WaitForExit();

    standardOutput.Append(process.StandardOutput.ReadToEnd());

    // ...
}

4voto

Ben Points 353

Pour une réponse plus spécifique directement liée à ffmpeg, passer la commande "-report" dans ffmpeg fera en sorte qu'il vide un journal dans le répertoire courant avec ce qui a été dit dans l'affichage du processus.

rapport

Transfert de la ligne de commande complète et de la sortie de la console dans un fichier nommé programme-YYYYMMDD-HHMMSS.log dans le répertoire courant. Ce fichier peut être utile pour les rapports de bogues. Il implique également -loglevel verbose.

Remarque : le fait de donner à la variable d'environnement FFREPORT n'importe quelle valeur a pour effet d'augmenter la valeur de l'option même effet.

Desde Documentation FFMpeg .

2voto

Michael Vasquez Points 36

Je sais que cette question est ancienne, mais je vais quand même la compléter.

Si tout ce que vous souhaitez faire est d'afficher la sortie d'un processus en ligne de commande, et que vous lancez le processus à partir d'une fenêtre console, il vous suffit de rediriger l'entrée standard (oui, je sais que cela semble faux, mais cela fonctionne).

Donc :

System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(ffmpegPath, myParams);
p.UseShellExecute = false;
p.RedirectStandardInput = true;
p.Start();
p.WaitForExit();

Ça ferait l'affaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X