_Q12_ Ответов: 2

Вывод консольного приложения в winapp


У меня есть консольное приложение, которое подсчитывает процент вверх, и это занимает некоторое время, чтобы закончить.
Я могу вызвать и прочитать его вывод внутри winapplication, но внутри одной глобальной переменной, которая собирает все, пока работает консольное приложение, и после того, как все будет закончено, myvar наконец отобразит его содержимое. Практично, но не мило !
Я хочу видеть обновление вывода консоли в прямом эфире в моем приложении win !
Спасибо!

Что я уже пробовал:

       void ComandExecute()
        {
            //if (label1.InvokeRequired)  //I tried this but is getting skipped
            {

                string nl = "\r\n";
                string vvvh = "";

                Main.Text = "";
                var processInfo = new ProcessStartInfo("console_app.exe", "output> " + str1);
                processInfo.CreateNoWindow = true;
                processInfo.UseShellExecute = false;
                processInfo.RedirectStandardError = true;
                processInfo.RedirectStandardOutput = true;

                var process = Process.Start(processInfo);

//I tried here to obtain the output into my label but i get error01
//error01 says: 
//" Cross-thread operation not valid: Control 'label1' accessed from a thread other than the //thread it was created on. "

                process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
                    {
                        label1.Text += e.Data + nl; label1.Refresh(); //<< error at this line
                    };
                process.BeginOutputReadLine();


                process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
                vvvh += "error>>" + e.Data + nl;
                label1.Text += vvvh; label1.Refresh();
                process.BeginErrorReadLine();


                process.WaitForExit();
                vvvh += "ExitCode: " + process.ExitCode + nl;
                process.Close();

                Main.Text = vvvh;
                label1.Text = Main.Text;
            }
        }

2 Ответов

Рейтинг:
6

Richard MacCutchan

Если вам нужна информация в приложении Windows, то используйте Класс BackgroundWorker (System.ComponentModel) | Microsoft Docs[^] чтобы сделать расчеты. Таким образом, вы можете обновить значение по мере его вычисления.


_Q12_

Я даю ему еще одну попытку сегодня, и код из вашей ссылки прекрасно справился со своей работой.
Большое вам спасибо за помощь и понимание.

Richard MacCutchan

Добро пожаловать.

Рейтинг:
1

OriginalGriff

Во-первых, добавьте свои обработчики до вы вызываете запуск процесса - или в противном случае вы потеряете все данные, которые приложение генерирует, прежде чем добавить обработчики.

Во-вторых, события DataReceived всегда обрабатываются в отдельном потоке, если вы не зададите Процесс.Свойство SynchronizingObject (System.Диагностика) | Microsoft Docs[^] который синхронизирует данные в потоке пользовательского интерфейса для вас.

Имейте в виду, что событие OutputDataReceived работает только в полных строках.


_Q12_

Я не знаю, что такое Хэндлер.
Программа работает нормально, если я оставляю myvar собирать данные, а не мое маленькое вмешательство с меткой на этой строке. Но он делает это все сразу, а потом показывает результат.

Dave Kreskowiak

обработчики событий.... те строки, которые упоминают "+= (отправитель объекта,...)", настраивают обработчики событий.

На самом деле вы не писали этот код, не так ли? Скопировать и вставить?

_Q12_

да, я копирую и вставляю большую его часть.
Я получаю некоторые результаты, но не те, которые мне действительно нужны.
Спасибо Вам за всю вашу добрую помощь и понимание до сих пор !

_Q12_

@ Dave Kreskowiak, я привык называть их просто "событиями". Я не привык называть их "обработчиками", но теперь я понимаю, что у них есть 3 названия для одного и того же: "событие", "обработчик" и "обработчик событий". Я знал о них с такими именами, но на самом деле использовал только 1 имя. Спасибо за разъяснение.

OriginalGriff

"Событие" - это то, что вы обрабатываете; "обработчик" или "обработчик событий" - это код, который запускается, когда происходит событие.
TextBox.TextChanged-это событие: ваш код, который проверяет, что набрал пользователь, является обработчиком.

_Q12_

Спасибо!
На самом деле, это очень хорошее объяснение.
Я всегда думал, что код внутри события-это просто "выполняемый код", но теперь он становится легким, его "обработчик событий|обработчик".

_Q12_

Я уже тестирую код мистера OriginalGriff по ссылке, которую он предложил.

_Q12_

Я попробовал ваш код, и я все еще получаю полный текст, а не строчку за строкой, обновление, на лету, как я хочу.
пустота ComandExecute()
{
использование (Process process = новый процесс())
{
ProcessStartInfo processInfo = новый ProcessStartInfo("console_app.exe", "-F " + str1);
процесс.StartInfo = processInfo;
//processInfo.CreateNoWindow = true;
processInfo.Значение свойства useshellexecute = false в;
//processInfo.RedirectStandardError = истина;
processInfo.RedirectStandardOutput = true в;
процесс.Начать();


// label1.Текст = процесс.Стандартный вывод.BaseStream.EndRead(...что-то здесь есть...) ;
этикетка 1.Текст = процесс.StandardOutput.С readline();
метка1.Обновить();


процесс.Exited += новый EventHandler(MyProcessExited);
процесс.EnableRaisingEvents = true;
процесс.SynchronizingObject = button1;
Ящик для сообщений.Show("ожидание завершения процесса....");


этикетка 1.Текст = процесс.StandardOutput.ReadToEnd();
метка1.Обновить();


процесс.WaitForExit();
}
}