Ранее в статье Читаем стандартный вывод консольного приложения + DOS to UTF я писал как подключаться и читать стандартный вывод консольных приложений. Все это конечно работает хорошо, но есть один нюанс – событие на которое мы подписываемся (pr.OutputDataReceived += new DataReceivedEventHandler(sortOutputHandler)) возникает только тогда, когда в консольной программе происходит переход на новую строку. В этот момент нам возвращается весь буфер строки. А так, как в одной строке можно вывести кучу информации используя, например, служебный символ \b (backspace), то для чтения текста из консоли код из предыдущей статьи может и не подойти.
На помощь приходит следующее решение. Мы создаем свой поток и подключаем к нему стандартный вывод консоли. Далее мы просто читаем наш поток и разбираем его.
В следующем коде используются переменные:
sr – наш поток, с которым мы работаем.
nsize – количество символов, которые будут читаться за раз.
buffer – массив в котором будут храниться кода символов. Сюда входят и служебные символы – переход на другую строку, backspace, tab и т.д.
sOut – ассинхронный вызов. В данном случае служит как заглушка.
В итоге получаем следующий код.
1 |
private void run(string utilityName, string arguments) |
7 |
Byte[] buffer = new Byte[nsize]; |
8 |
AsyncCallback sOut = new AsyncCallback(Res); |
11 |
Process pr = new Process(); |
13 |
pr.StartInfo.FileName = utilityName; |
15 |
pr.StartInfo.Arguments = arguments; |
17 |
pr.StartInfo.UseShellExecute = false; |
19 |
pr.StartInfo.RedirectStandardOutput = true; |
21 |
pr.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(866); |
23 |
pr.StartInfo.CreateNoWindow = true; |
25 |
pr.EnableRaisingEvents = true; |
27 |
pr.Exited += new EventHandler(whenExitProcess); |
32 |
sr = pr.StandardOutput.BaseStream; |
33 |
sr.BeginRead(buffer, 0, nsize, sOut, null); |
36 |
while (sr.Read(buffer, 0, nsize) > 0) |
39 |
string sym5 = System.Text.Encoding.GetEncoding(866).GetString(buffer)); |
44 |
catch (Exception error) |
46 |
MessageBox.Show("Ошибка при запуске!\n" + error.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); |
53 |
/// <param name="ar"></param> |
54 |
void Res(IAsyncResult ar) |
59 |
private void whenExitProcess(Object sender, EventArgs e) |
Вот что у нас получилось. Как видите читать можно хоть по 20 символов, задавая размер буфера. Задавайте вопросы, будем разбирать что не понятно.