Консольный вывод. Читаем посимвольно.

И немного рекламы:

Ранее в статье Читаем стандартный вывод консольного приложения + DOS to UTF я писал как подключаться и читать стандартный вывод консольных приложений. Все это конечно работает хорошо, но есть один нюанс — событие на которое мы подписываемся (pr.OutputDataReceived += new DataReceivedEventHandler(sortOutputHandler)) возникает только тогда, когда в консольной программе происходит переход на новую строку. В этот момент нам возвращается весь буфер строки. А так, как в одной строке можно вывести кучу информации используя, например, служебный символ \b (backspace), то для чтения текста из консоли код из предыдущей статьи может и не подойти.

На помощь приходит следующее решение. Мы создаем свой поток и подключаем к нему стандартный вывод консоли. Далее мы просто читаем наш поток и разбираем его.

В следующем коде используются переменные:
sr — наш поток, с которым мы работаем.
nsize — количество символов, которые будут читаться за раз.
buffer — массив в котором будут храниться кода символов. Сюда входят и служебные символы — переход на другую строку, backspace, tab и т.д.
sOut — ассинхронный вызов. В данном случае служит как заглушка.

В итоге получаем следующий код.

private void run(string utilityName, string arguments)
{
    try
    {
        Stream sr; //поток из которого будем читать вывод консоли
        int nsize = 5; //по сколько символов за раз будем читать. Можно установить и больше, и меньше
        Byte[] buffer = new Byte[nsize]; //здесь то? что будем читать - размер количество символов
        AsyncCallback sOut = new AsyncCallback(Res); //ассинхронный вызов

        //создаем новый процесс, который будет работать с консолью
        Process pr = new Process();
        //задаем имя запускного файла
        pr.StartInfo.FileName = utilityName;
        //задаем аргументы для этого файла
        pr.StartInfo.Arguments = arguments;
        //отключаем использование оболочки, чтобы можно было читать данные вывода
        pr.StartInfo.UseShellExecute = false;
        //перенаправляем данные вовода
        pr.StartInfo.RedirectStandardOutput = true;
        //задаем кодировку, чтобы читать кириллические символы
        pr.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(866);
        //запрещаем создавать окно для запускаемой программы
        pr.StartInfo.CreateNoWindow = true;
        //включаем возможность определять когда происходит выход из программы, которую будем запускать
        pr.EnableRaisingEvents = true;
        //подписываемся на событие, когда процесс завершит работу
        pr.Exited += new EventHandler(whenExitProcess);

		//запускаем процесс
        pr.Start();

        sr = pr.StandardOutput.BaseStream; //перенаправляем стандартный вывод в наш поток
        sr.BeginRead(buffer, 0, nsize, sOut, null); //начинаем читать стандартный вывод консоли

		//читаем поток, пока есть что читать
        while (sr.Read(buffer, 0, nsize) > 0)
        {
            //переводим массив символов в строку через кодировку dos866
            string sym5 = System.Text.Encoding.GetEncoding(866).GetString(buffer));
			//далее выполняем действия с полученным текстом
			//.....
        }
    }
    catch (Exception error)
    {
        MessageBox.Show("Ошибка при запуске!\n" + error.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

/// <summary>
/// просто заглушка
/// </summary>
/// <param name="ar"></param>
void Res(IAsyncResult ar)
{
}

//завершение запущенного процесса
private void whenExitProcess(Object sender, EventArgs e)
{
    //данные об окончании работы программы
}

Вот что у нас получилось. Как видите читать можно хоть по 20 символов, задавая размер буфера. Задавайте вопросы, будем разбирать что не понятно.
Так же можно купить люстру в Киеве

Популярность: 5%

Еще по этой теме:

  1. Читаем стандартный вывод консольного приложения + DOS to UTF
  2. Альтернативные потоки данных NTFS с примером использования на C#

Теги: ,

Если у вас возникли вопросы, вы можете оставить их в комментариях

Оставить комментарий

(обязательно)

(обязательно)