2014-02-18 18 views
9

Ich habe eine Konsolenanwendung, die ich zu automatisieren versuche, indem ich den Standard-Eingabestream des Prozesses umleite. Im manuellen Modus nach dem Öffnen der Anwendung, wartet es auf Benutzereingaben wie unten, enter image description hereUmleiten der Standardeingabe der Konsolenanwendung

ich den Prozess erstellt mit umgeleitet Standardeingabe Stroms Codeausschnitt wird wie folgt,

Process newProcess = new Process(); 
newProcess.StartInfo.FileName = exeName; 
newProcess.StartInfo.Arguments = argsLine; 
newProcess.StartInfo.UseShellExecute = false; 
newProcess.StartInfo.RedirectStandardOutput = false ; 
newProcess.StartInfo.CreateNoWindow = false; 
newProcess.StartInfo.RedirectStandardInput = true; 
newProcess.Start(); 

Aber die Schaffung Prozess wie diesem gibt eine unendliche Schleife unten, enter image description here

Es ist wie ich kontinuierlich an den Eingangsstrom Prozess gezeigt Enter Tastaturbefehl bin das Senden. Kann mir jemand darauf hinweisen, was ich hier falsch mache?

Ähnlich Umleitung Standardausgabe arbeitet auch nicht nach

newProcess.StartInfo.RedirectStandardOutput = true

machen aber ich kann damit verwalten.

Funktioniert die Umleitung von Standardstreams mit allen Konsolenanwendungen oder gibt es eine Ausnahme?

+1

Wie sieht der Code in der Schleife aus? –

+0

@Watson Ich habe den Code der Konsolenanwendung nicht. Es ist ein Drittanbieter-Tool. – Vignesh

+2

Bitte geben Sie keine Informationen über eine Sprache an, die in einem Fragentitel verwendet wird, es sei denn, es würde ohne sie keinen Sinn ergeben. Tags dienen diesem Zweck. –

Antwort

15

Hier ist eine Klasse, die ich geschrieben habe, um diese Art von Sachen zu behandeln. Fühlen Sie sich frei, es zu benutzen. Sein Zweck ist es, eine Konsolenanwendung zu starten und mit ihr "zu reden". Es hat auch die Fähigkeit, die Ausgabe zu empfangen. Viel Glück.

using System; 
using System.Diagnostics; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

public class ConsoleAppManager 
{ 
    private readonly string appName; 
    private readonly Process process = new Process(); 
    private readonly object theLock = new object(); 
    private SynchronizationContext context; 
    private string pendingWriteData; 

    public ConsoleAppManager(string appName) 
    { 
     this.appName = appName; 

     this.process.StartInfo.FileName = this.appName; 
     this.process.StartInfo.RedirectStandardError = true; 
     this.process.StartInfo.StandardErrorEncoding = Encoding.UTF8; 

     this.process.StartInfo.RedirectStandardInput = true; 
     this.process.StartInfo.RedirectStandardOutput = true; 
     this.process.EnableRaisingEvents = true; 
     this.process.StartInfo.CreateNoWindow = true; 

     this.process.StartInfo.UseShellExecute = false; 

     this.process.StartInfo.StandardOutputEncoding = Encoding.UTF8; 

     this.process.Exited += this.ProcessOnExited; 
    } 

    public event EventHandler<string> ErrorTextReceived; 
    public event EventHandler ProcessExited; 
    public event EventHandler<string> StandartTextReceived; 

    public int ExitCode 
    { 
     get { return this.process.ExitCode; } 
    } 

    public bool Running 
    { 
     get; private set; 
    } 

    public void ExecuteAsync(params string[] args) 
    { 
     if (this.Running) 
     { 
      throw new InvalidOperationException(
       "Process is still Running. Please wait for the process to complete."); 
     } 

     string arguments = string.Join(" ", args); 

     this.process.StartInfo.Arguments = arguments; 

     this.context = SynchronizationContext.Current; 

     this.process.Start(); 
     this.Running = true; 

     new Task(this.ReadOutputAsync).Start(); 
     new Task(this.WriteInputTask).Start(); 
     new Task(this.ReadOutputErrorAsync).Start(); 
    } 

    public void Write(string data) 
    { 
     if (data == null) 
     { 
      return; 
     } 

     lock (this.theLock) 
     { 
      this.pendingWriteData = data; 
     } 
    } 

    public void WriteLine(string data) 
    { 
     this.Write(data + Environment.NewLine); 
    } 

    protected virtual void OnErrorTextReceived(string e) 
    { 
     EventHandler<string> handler = this.ErrorTextReceived; 

     if (handler != null) 
     { 
      if (this.context != null) 
      { 
       this.context.Post(delegate { handler(this, e); }, null); 
      } 
      else 
      { 
       handler(this, e); 
      } 
     } 
    } 

    protected virtual void OnProcessExited() 
    { 
     EventHandler handler = this.ProcessExited; 
     if (handler != null) 
     { 
      handler(this, EventArgs.Empty); 
     } 
    } 

    protected virtual void OnStandartTextReceived(string e) 
    { 
     EventHandler<string> handler = this.StandartTextReceived; 

     if (handler != null) 
     { 
      if (this.context != null) 
      { 
       this.context.Post(delegate { handler(this, e); }, null); 
      } 
      else 
      { 
       handler(this, e); 
      } 
     } 
    } 

    private void ProcessOnExited(object sender, EventArgs eventArgs) 
    { 
     this.OnProcessExited(); 
    } 

    private async void ReadOutputAsync() 
    { 
     var standart = new StringBuilder(); 
     var buff = new char[1024]; 
     int length; 

     while (this.process.HasExited == false) 
     { 
      standart.Clear(); 

      length = await this.process.StandardOutput.ReadAsync(buff, 0, buff.Length); 
      standart.Append(buff.SubArray(0, length)); 
      this.OnStandartTextReceived(standart.ToString()); 
      Thread.Sleep(1); 
     } 

     this.Running = false; 
    } 

    private async void ReadOutputErrorAsync() 
    { 
     var sb = new StringBuilder(); 

     do 
     { 
      sb.Clear(); 
      var buff = new char[1024]; 
      int length = await this.process.StandardError.ReadAsync(buff, 0, buff.Length); 
      sb.Append(buff.SubArray(0, length)); 
      this.OnErrorTextReceived(sb.ToString()); 
      Thread.Sleep(1); 
     } 
     while (this.process.HasExited == false); 
    } 

    private async void WriteInputTask() 
    { 
     while (this.process.HasExited == false) 
     { 
      Thread.Sleep(1); 

      if (this.pendingWriteData != null) 
      { 
       await this.process.StandardInput.WriteLineAsync(this.pendingWriteData); 
       await this.process.StandardInput.FlushAsync(); 

       lock (this.theLock) 
       { 
        this.pendingWriteData = null; 
       } 
      } 
     } 
    } 
} 
+0

Danke für den Code. Da ich VS2010 verwende, kann ich Async nicht verwenden und abwarten. :(Ich habe den Code nach dem Bearbeiten und Entfernen aller Async-Teil (nicht sicher, es ist richtig), aber ich konfrontiert das gleiche Problem, das ich in der Frage mit dem bearbeiteten Code auch erklärt .. – Vignesh

+4

Sind Sie sicher, dass die Antwort so viel Rauschen wie Regionen enthalten muss und offensichtliche XML-Kommentare? – abatishchev

+0

Sorry, dass es kopiert wurde aus einer Datei, die von stylecop formatiert wurde –

1

die vorherige Antwort Folgen, werde ich die Erweiterungsmethode von Subarray nur hinzufügen, nur für den Fall diese Klasse, um Ihren Code hinzufügen, wo es in jeder Klasse ist nicht (der Code verschachtelt sah nicht lesbar ein Kommentar, also habe ich es hier hinzugefügt)

public static class CharArrayExtensions 
{ 
    public static char[] SubArray(this char[] input,int startIndex, int length) 
    { 
     List<char> result= new List<char>(); 
     for (int i = startIndex; i < length; i++) 
     { 
      result.Add(input[i]); 
     } 

     return result.ToArray(); 
    } 
} 
Verwandte Themen