134 votes

Comment lancer un processus et capturer son STDOUT en .NET ?

J'ai besoin de créer un processus enfant qui est une application console, et de capturer sa sortie.

J'ai écrit le code suivant pour une méthode :

string retMessage = String.Empty;
ProcessStartInfo startInfo = new ProcessStartInfo();
Process p = new Process();

startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardInput = true;

startInfo.UseShellExecute = false;
startInfo.Arguments = command;
startInfo.FileName = exec;

p.StartInfo = startInfo;
p.Start();

p.OutputDataReceived += new DataReceivedEventHandler
(
    delegate(object sender, DataReceivedEventArgs e)
    {
        using (StreamReader output = p.StandardOutput)
        {
            retMessage = output.ReadToEnd();
        }
    }
);

p.WaitForExit();

return retMessage;

Cependant, cela ne donne rien. Je ne crois pas que le OutputDataReceived est rappelé, ou l'événement WaitForExit() peut bloquer le fil d'exécution, de sorte qu'elle ne fera jamais de rappel.

Des conseils ?

EDITAR: On dirait que j'en faisais trop avec le rappel. Je le fais :

return p.StandardOutput.ReadToEnd(); 

Il semble que cela fonctionne bien.

154voto

Judah Himango Points 27365

Voici un code dont j'ai vérifié le fonctionnement. Je l'utilise pour faire apparaître MSBuild et écouter sa sortie :

process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => Console.WriteLine("received output: {0}", args.Data);
process.Start();
process.BeginOutputReadLine();

35voto

Je viens d'essayer de faire la même chose et ce qui suit a fonctionné pour moi :

StringBuilder outputBuilder;
ProcessStartInfo processStartInfo;
Process process;

outputBuilder = new StringBuilder();

processStartInfo = new ProcessStartInfo();
processStartInfo.CreateNoWindow = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.UseShellExecute = false;
processStartInfo.Arguments = "<insert command line arguments here>";
processStartInfo.FileName = "<insert tool path here>";

process = new Process();
process.StartInfo = processStartInfo;
// enable raising events because Process does not raise events by default
process.EnableRaisingEvents = true;
// attach the event handler for OutputDataReceived before starting the process
process.OutputDataReceived += new DataReceivedEventHandler
(
    delegate(object sender, DataReceivedEventArgs e)
    {
        // append the new data to the data already read-in
        outputBuilder.Append(e.Data);
    }
);
// start the process
// then begin asynchronously reading the output
// then wait for the process to exit
// then cancel asynchronously reading the output
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
process.CancelOutputRead();

// use the output
string output = outputBuilder.ToString();

21voto

Sam Points 3542

Voici un code complet et simple pour faire cela. Cela a bien fonctionné quand je l'ai utilisé.

var processStartInfo = new ProcessStartInfo
{
    FileName = @"C:\SomeProgram",
    Arguments = "Arguments",
    RedirectStandardOutput = true,
    UseShellExecute = false
};
var process = Process.Start(processStartInfo);
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Notez que cela ne prend en compte que les sortie ; il ne capture pas la norme erreur . Si vous voulez les deux, utilisez cette technique pour chaque flux.

20voto

JaredPar Points 333733

Il semble que deux de vos lignes ne soient pas dans l'ordre. Vous lancez le processus avant de mettre en place un gestionnaire d'événement pour capturer la sortie. Il est possible que le processus soit en train de se terminer avant que le gestionnaire d'événements soit ajouté.

Intervertissez les lignes comme suit.

p.OutputDataReceived += ...
p.Start();

3voto

SoapBox Points 14183

Vous devez appeler p.Start() pour exécuter réellement le processus après avoir défini le StartInfo. En l'état actuel des choses, votre fonction est probablement suspendue à l'appel WaitForExit() parce que le processus n'a jamais été réellement lancé.

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