C #: вывод приложения консоли Redirect: как очистить вывод?

Я создаю внешнее консольное приложение и перенаправляю asynchronous вывод.
как показано в этом сообщении SO

Моя проблема заключается в том, что, похоже, что порожденный процесс должен произвести определенный объем вывода, прежде чем я получу уведомление о событии OutputDataReceived .

Я хочу получить событие OutputDataReceived как можно скорее.

У меня есть приложение для переадресации без костей, и вот несколько замечаний:
1. Когда я называю простой «while (true) print (« X »); консольное приложение (C #) Я получаю выходное событие немедленно. 2. Когда я вызываю приложение 3d-вечеринки, которое я пытаюсь обернуть из командной строки, я вижу линейный вывод.
3. Когда я вызываю это приложение для 3d-вечеринки из моей обложки с голыми костями (см. 1), вывод выводится в виде кусков (размером около одной страницы).

Что происходит внутри этого приложения?

FYI: рассматриваемое приложение представляет собой «Экземпляр данных USBee DX Data Exctarctor (Async) v1.0».

Я сделал еще несколько исследований и исправил для Microsoft class Process. Но поскольку мой последний ответ был удален без причины, мне пришлось создать новый.

Итак, возьмите этот пример …

Создайте приложение Windows и вставьте богатое текстовое поле в основную форму, затем добавьте это в загрузку формы …

Process p = new Process() { StartInfo = new ProcessStartInfo() { FileName = "cmd.exe", CreateNoWindow = true, UseShellExecute = false, ErrorDialog = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, }, EnableRaisingEvents = true, SynchronizingObject = this }; p.OutputDataReceived += (s, ea) => this.richTextBox1.AppendText(ea.Data); p.Start(); p.BeginOutputReadLine(); 

Это выведет что-то вроде этого …

 Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. 

Событие OutputDataReceived не запускается для последней строки. После некоторого ILSpying кажется, что это преднамеренно, потому что последняя строка не заканчивается crlf, она предполагает, что есть больше сообщений и добавляет их к началу следующего события.

Чтобы исправить это, я написал оболочку для classа Process и взял с собой некоторые из необходимых внутренних classов, чтобы все работало аккуратно. Вот class FixedProcess …

 using System; using System.Collections; using System.IO; using System.Text; using System.Threading; namespace System.Diagnostics { internal delegate void UserCallBack(string data); public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e); public class FixedProcess : Process { internal AsyncStreamReader output; internal AsyncStreamReader error; public event DataReceivedEventHandler OutputDataReceived; public event DataReceivedEventHandler ErrorDataReceived; public new void BeginOutputReadLine() { Stream baseStream = StandardOutput.BaseStream; this.output = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedOutputReadNotifyUser), StandardOutput.CurrentEncoding); this.output.BeginReadLine(); } public void BeginErrorReadLine() { Stream baseStream = StandardError.BaseStream; this.error = new AsyncStreamReader(this, baseStream, new UserCallBack(this.FixedErrorReadNotifyUser), StandardError.CurrentEncoding); this.error.BeginReadLine(); } internal void FixedOutputReadNotifyUser(string data) { DataReceivedEventHandler outputDataReceived = this.OutputDataReceived; if (outputDataReceived != null) { DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) { this.SynchronizingObject.Invoke(outputDataReceived, new object[] { this, dataReceivedEventArgs }); return; } outputDataReceived(this, dataReceivedEventArgs); } } internal void FixedErrorReadNotifyUser(string data) { DataReceivedEventHandler errorDataReceived = this.ErrorDataReceived; if (errorDataReceived != null) { DataReceivedEventArgs dataReceivedEventArgs = new DataReceivedEventArgs(data); if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired) { this.SynchronizingObject.Invoke(errorDataReceived, new object[] { this, dataReceivedEventArgs }); return; } errorDataReceived(this, dataReceivedEventArgs); } } } internal class AsyncStreamReader : IDisposable { internal const int DefaultBufferSize = 1024; private const int MinBufferSize = 128; private Stream stream; private Encoding encoding; private Decoder decoder; private byte[] byteBuffer; private char[] charBuffer; private int _maxCharsPerBuffer; private Process process; private UserCallBack userCallBack; private bool cancelOperation; private ManualResetEvent eofEvent; private Queue messageQueue; private StringBuilder sb; private bool bLastCarriageReturn; public virtual Encoding CurrentEncoding { get { return this.encoding; } } public virtual Stream BaseStream { get { return this.stream; } } internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding) : this(process, stream, callback, encoding, 1024) { } internal AsyncStreamReader(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) { this.Init(process, stream, callback, encoding, bufferSize); this.messageQueue = new Queue(); } private void Init(Process process, Stream stream, UserCallBack callback, Encoding encoding, int bufferSize) { this.process = process; this.stream = stream; this.encoding = encoding; this.userCallBack = callback; this.decoder = encoding.GetDecoder(); if (bufferSize < 128) { bufferSize = 128; } this.byteBuffer = new byte[bufferSize]; this._maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize); this.charBuffer = new char[this._maxCharsPerBuffer]; this.cancelOperation = false; this.eofEvent = new ManualResetEvent(false); this.sb = null; this.bLastCarriageReturn = false; } public virtual void Close() { this.Dispose(true); } void IDisposable.Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing && this.stream != null) { this.stream.Close(); } if (this.stream != null) { this.stream = null; this.encoding = null; this.decoder = null; this.byteBuffer = null; this.charBuffer = null; } if (this.eofEvent != null) { this.eofEvent.Close(); this.eofEvent = null; } } internal void BeginReadLine() { if (this.cancelOperation) { this.cancelOperation = false; } if (this.sb == null) { this.sb = new StringBuilder(1024); this.stream.BeginRead(this.byteBuffer, 0, this.byteBuffer.Length, new AsyncCallback(this.ReadBuffer), null); return; } this.FlushMessageQueue(); } internal void CancelOperation() { this.cancelOperation = true; } private void ReadBuffer(IAsyncResult ar) { int num; try { num = this.stream.EndRead(ar); } catch (IOException) { num = 0; } catch (OperationCanceledException) { num = 0; } if (num == 0) { lock (this.messageQueue) { if (this.sb.Length != 0) { this.messageQueue.Enqueue(this.sb.ToString()); this.sb.Length = 0; } this.messageQueue.Enqueue(null); } try { this.FlushMessageQueue(); return; } finally { this.eofEvent.Set(); } } int chars = this.decoder.GetChars(this.byteBuffer, 0, num, this.charBuffer, 0); this.sb.Append(this.charBuffer, 0, chars); this.GetLinesFromStringBuilder(); this.stream.BeginRead(this.byteBuffer, 0, this.byteBuffer.Length, new AsyncCallback(this.ReadBuffer), null); } private void GetLinesFromStringBuilder() { int i = 0; int num = 0; int length = this.sb.Length; if (this.bLastCarriageReturn && length > 0 && this.sb[0] == '\n') { i = 1; num = 1; this.bLastCarriageReturn = false; } while (i < length) { char c = this.sb[i]; if (c == '\r' || c == '\n') { if (c == '\r' && i + 1 < length && this.sb[i + 1] == '\n') { i++; } string obj = this.sb.ToString(num, i + 1 - num); num = i + 1; lock (this.messageQueue) { this.messageQueue.Enqueue(obj); } } i++; } // Flush Fix: Send Whatever is left in the buffer string endOfBuffer = this.sb.ToString(num, length - num); lock (this.messageQueue) { this.messageQueue.Enqueue(endOfBuffer); num = length; } // End Flush Fix if (this.sb[length - 1] == '\r') { this.bLastCarriageReturn = true; } if (num < length) { this.sb.Remove(0, num); } else { this.sb.Length = 0; } this.FlushMessageQueue(); } private void FlushMessageQueue() { while (this.messageQueue.Count > 0) { lock (this.messageQueue) { if (this.messageQueue.Count > 0) { string data = (string)this.messageQueue.Dequeue(); if (!this.cancelOperation) { this.userCallBack(data); } } continue; } break; } } internal void WaitUtilEOF() { if (this.eofEvent != null) { this.eofEvent.WaitOne(); this.eofEvent.Close(); this.eofEvent = null; } } } public class DataReceivedEventArgs : EventArgs { internal string _data; /// Gets the line of characters that was written to a redirected  output stream. /// The line that was written by an associated  to its redirected  or  stream. /// 2 public string Data { get { return this._data; } } internal DataReceivedEventArgs(string data) { this._data = data; } } } 

Придерживайтесь этого в своем проекте, а затем меняйте …

 Process p = new Process() { .... 

в

 FixedProcess p = new FixedProcess() { .... 

Теперь ваше приложение должно отобразить что-то вроде этого …

 Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\Projects\FixedProcess\bin\Debug> 

без необходимости внесения каких-либо изменений в существующий код. Он также по-прежнему асинхронно и хорошо завербован. Одно из предостережений заключается в том, что теперь вы получите несколько событий для большого вывода с потенциальными перерывами между ними, поэтому вам придется самому справиться с этим сценарием. Кроме этого, все должно быть хорошо.

Проверьте этот ответ.

Как отправить ввод на консоль, как если бы пользователь печатал?

Идея заключается в том, что вы получите полученные полученные события, когда любой из них будет запущен после запуска процесса.

Похоже, проблема заключалась в том, что фиктивное приложение было написано в c #, которое автоматически сбрасывает вывод каждый каждый println, в то время как стороннее приложение было написано на c / c ++ и поэтому написано только при заполнении stdoutbuffer. Единственное решение, которое было найдено ive, – убедиться, что приложение c / c ++ сбрасывается после каждой печати или для установки его буфера на 0.

  • Заменить все объекты NSNull в NSDictionary
  • Просмотр моделей и инъекций зависимостей
  • Является ли bool родным C-типом?
  • Процесс приостановки в C #
  • Шифровать и расшифровать строку в C #?
  • Можно ли преобразовать обратный iterator в форвардный iterator?
  • C # получить эскиз из файла через windows api
  • Как мы можем показать индикатор выполнения для загрузки с помощью FtpWebRequest
  • Что означает «unsigned temp: 3» в структуре или объединении?
  • Как установить тайм-аут сеанса в web.config
  • проверить параметры вариационных шаблонов для уникальности
  • Давайте будем гением компьютера.