2009-03-09 8 views
1

J'ai une application graphique dans laquelle je lance une application console en utilisant la classe Process.Sortie partiellement lue de la sortie standard d'un autre processus créé à partir de l'application C#

Process p1 = new Process(); 
p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
p1.StartInfo.CreateNoWindow = true; 
p1.StartInfo.UseShellExecute = false; 
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe"); 
p1.StartInfo.Arguments = "/pn abc.exe /f \"temp1.txt\""; 
p1.StartInfo.RedirectStandardError = true; 
p1.StartInfo.RedirectStandardInput = true; 
p1.StartInfo.RedirectStandardOutput = true; 
p1.OutputDataReceived += new DataReceivedEventHandler(outputreceived); 
p1.ErrorDataReceived += new DataReceivedEventHandler(errorreceived); 
p1.Start(); 
tocmd = p1.StandardInput; 
p1.BeginOutputReadLine(); 
p1.BeginErrorReadLine(); 

Maintenant, j'ai un problème qui, si elle lit la sortie de la console de manière asynchrone, mais il semble déclencher l'événement uniquement lorsque la mémoire tampon interne est rempli d'une certaine quantité. Je veux qu'il affiche les données telles qu'elles sont. S'il y a 10 octets dans le tampon, laissez-le afficher les 10 octets. Mon programme implémente l'appel sleep() en interne, j'ai donc besoin d'imprimer les données jusqu'à ce qu'il se mette en veille.

Comment puis-je le faire?

=============

Comme il a été mentionné, la sortie est conduite en mémoire tampon, i essayé le changement suivant dans le code

p1.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
p1.StartInfo.CreateNoWindow = true; 
p1.StartInfo.UseShellExecute = false; 
p1.StartInfo.FileName = Path.Combine(basepath, "abc.exe"); 
p1.StartInfo.Arguments = pnswitch + " /f \"temp1.txt\""; 
p1.StartInfo.RedirectStandardError = false; 
p1.StartInfo.RedirectStandardInput = true; 
p1.StartInfo.RedirectStandardOutput = true; 
p1.Start(); 
tocmd = p1.StandardInput; 
MethodInvoker mi = new MethodInvoker(readout); 
mi.BeginInvoke(null, p1); 

et à l'intérieur de lecture i a écrit

void readout() 
    { 
     string str; 
     while ((str = p1.StandardOutput.ReadLine()) != null) 
     { 
      richTextBox1.Invoke(new UpdateOutputCallback(this.updateoutput), new object[] { str }); 
      p1.StandardOutput.BaseStream.Flush(); 
     } 
    } 

Donc je pense qu'il surveille maintenant quand chaque ligne est écrite et l'imprime correctement? cela aussi n'a pas fonctionné. Y a t-il quelque chose qui ne va

Répondre

3

Les données de sortie et d'erreur reçues sont mises en mémoire tampon et ne sont déclenchées que lorsqu'un saut de ligne est ajouté.

Votre meilleur pari est d'utiliser votre propre lecteur qui peut lire l'entrée, octet par octet. Obvioullyly, cela devrait être non-bloquant :)

+0

toute idée comment puis-je prendre pour faire mon lecteur? Je ne peux pas écrire une fonction qui surveille le flux stdoutput et en lit chaque fois qu'il a des données? –

+0

Oui, c'est l'idée. Vous lisez le StandardOutput d'un autre thread. – leppie

+0

J'ai changé le code, et l'ai fait lire ligne sage. pouvez-vous jeter un coup d'oeil? –

1

Pour ce faire, vous devez utiliser des opérations de lecture synchrones sur un flux redirigé. Votre code ressemblerait à ceci (MSDN Sample):

// Start the child process. 
Process p = new Process(); 
// Redirect the output stream of the child process. 
p.StartInfo.UseShellExecute = false; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.FileName = "Write500Lines.exe"; 
p.Start(); 
// Do not wait for the child process to exit before 
// reading to the end of its redirected stream. 
// p.WaitForExit(); 
// Read the output stream first and then wait. 
**string output = p.StandardOutput.ReadToEnd();** 
p.WaitForExit(); 

Pour obtenir un comportement async vous devez utiliser des threads.

Article MSDN here

+0

J'ai fait un appel asynchrone. Pouvez-vous jeter un coup d'oeil à la question mise à jour et commenter? –

Questions connexes