2009-01-06 16 views
48

Je développe une application Windows Forms qui nécessite que j'appelle un programme distinct pour effectuer une tâche. Le programme est une application console et j'ai besoin de rediriger la sortie standard de la console vers un TextBox dans mon programme.La sortie de la console de redirection vers la zone de texte dans un programme distinct

Je n'ai aucun problème à exécuter le programme depuis mon application, mais je ne sais pas comment rediriger la sortie vers mon application. J'ai besoin de capturer la sortie pendant que le programme fonctionne en utilisant des événements.

Le programme console n'est pas conçu pour s'arrêter de fonctionner tant que mon application ne s'arrête pas et que le texte change constamment à des intervalles aléatoires. Ce que je suis en train de faire est de simplement accrocher la sortie de la console pour déclencher un gestionnaire d'événements qui peut ensuite être utilisé pour mettre à jour le TextBox. J'utilise C# pour coder le programme et utiliser le framework .NET pour le développement. L'application d'origine n'est pas un programme .NET.

EDIT: Voici un exemple de code de ce que j'essaie de faire. Dans mon application finale, je remplacerai Console.WriteLine par du code pour mettre à jour le TextBox. J'ai essayé de définir un point d'arrêt dans mon gestionnaire d'événements, et il n'est même pas atteint.

void Method() 
    { 
     var p = new Process(); 
     var path = @"C:\ConsoleApp.exe"; 

     p.StartInfo.FileName = path; 
     p.StartInfo.UseShellExecute = false; 
     p.OutputDataReceived += p_OutputDataReceived; 

     p.Start(); 
    } 

    static void p_OutputDataReceived(object sender, DataReceivedEventArgs e) 
    { 
     Console.WriteLine(">>> {0}", e.Data); 
    } 
+0

Où est 'InputDataReceived'? –

Répondre

69

Cela fonctionne pour moi:

void RunWithRedirect(string cmdPath) 
{ 
    var proc = new Process(); 
    proc.StartInfo.FileName = cmdPath; 

    // set up output redirection 
    proc.StartInfo.RedirectStandardOutput = true; 
    proc.StartInfo.RedirectStandardError = true;  
    proc.EnableRaisingEvents = true; 
    proc.StartInfo.CreateNoWindow = true; 
    // see below for output handler 
    proc.ErrorDataReceived += proc_DataReceived; 
    proc.OutputDataReceived += proc_DataReceived; 

    proc.Start(); 

    proc.BeginErrorReadLine(); 
    proc.BeginOutputReadLine(); 

    proc.WaitForExit(); 
} 

void proc_DataReceived(object sender, DataReceivedEventArgs e) 
{ 
    // output will be in string e.Data 
} 
+0

Exactement ce que je voulais :) –

+4

J'ai découvert que parfois (à la sortie du programme) e.Data est nulle, donc vous devez vérifier si e.Data! = Null! – mmmmmmmm

+0

+1 La première fois que j'ai vu quelque chose de ce genre était dans EditPlus. Maintenant, je peux le faire dans mes programmes .NET. Merci mec! –

1
+0

Pas tout à fait, j'ai besoin de capturer du texte pendant qu'il est écrit sur stdout. –

+0

Si vous suivez le lien dans la publication, vous verrez le code pour cela ici: http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/52e40c0f-66c7-49b1-ba48-457a1ff4a58d/ –

+0

Oui, mais ce code ne s'exécute qu'une seule fois. J'ai mis à jour ma question pour clarifier ce que je tente de faire. –

4

Vous pouvez utiliser le code

 MemoryStream mem = new MemoryStream(1000); 
     StreamWriter writer = new StreamWriter(mem); 
     Console.SetOut(writer); 

     Assembly assembly = Assembly.LoadFrom(@"C:\ConsoleApp.exe"); 
     assembly.EntryPoint.Invoke(null, null); 
     writer.Close(); 

     string s = Encoding.Default.GetString(mem.ToArray()); 
     mem.Close(); 
+8

Si "C: \ ConsoleApp.exe" n'est pas une application .Net, cela ne fonctionnera pas! – mmmmmmmm

+0

oui c'est vrai –

1

suivant, j'ai ajouté un certain nombre de méthodes d'aide au O2 Platform (projet Open Source) qui vous permettent facilement script une interaction avec un autre processus via la sortie et l'entrée de la console (voir http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs)

Aussi utile pour vous pourrait être l'API qui permet la viewi ng de la sortie console du processus en cours (dans une fenêtre de contrôle ou une fenêtre contextuelle existante). Voir ce billet de blog pour plus de détails: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (ce blog contient également des détails sur comment consommer la sortie console de nouveaux processus)

0

Merci à Marc Maxham pour sa réponse qui m'a fait gagner du temps! Comme Jon de tous les métiers l'a remarqué, UseShellExecute doit être défini sur false afin de rediriger les flux d'E/S, sinon l'appel Start() lève une exception InvalidOperationException.

Voici ma modification du code où txtOut est un readonly WPF Textbox

void RunWithRedirect(string cmdargs) 
    { 
     var proc = new Process() 
     { 
      StartInfo = new ProcessStartInfo("cmd.exe", "/k " + cmdargs) 
      { 
       RedirectStandardOutput = true, 
       RedirectStandardError = true, 
       CreateNoWindow = true 
      }, 
      EnableRaisingEvents = true 
     }; 

     // see below for output handler 
     proc.ErrorDataReceived += proc_DataReceived; 
     proc.OutputDataReceived += proc_DataReceived; 

     proc.Start(); 

     proc.BeginErrorReadLine(); 
     proc.BeginOutputReadLine(); 

     proc.WaitForExit(); 
    } 

    void proc_DataReceived(object sender, DataReceivedEventArgs e) 
    { 
     if (e.Data != null) 
      Dispatcher.BeginInvoke(new Action(() => txtOut.Text += (Environment.NewLine + e.Data))); 
    } 
+0

Veuillez modifier la réponse originale et non la poster pour que l'auteur ait le crédit (y) –