Захват Консоли, В Реальном Времени

09.08.2013
5
0
#1
Программа выводить текст с консоли в Memo, но только после завершения консольного приложения.
Как сделать вывод в реальном времени?
C++:
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
#define READ_BUFFER_SIZE 1024
String AppName = "E:\\1.exe"; // Консольное приложение
SECURITY_ATTRIBUTES Security;
HANDLE ReadPipe, WritePipe;
STARTUPINFO Start;
TProcessInformation ProcessInfo;
char *Buffer, Data;
DWORD BytesRead, Apprunning;
int Result, DataSize;

Security.nLength = sizeof(TSecurityAttributes);
Security.bInheritHandle = true;
Security.lpSecurityDescriptor = NULL;

if (CreatePipe(&ReadPipe, &WritePipe, &Security, 0))
{
Buffer = new char[READ_BUFFER_SIZE + 1];

memset(&Start, 0, sizeof(Start));
Start.cb = sizeof(Start);
Start.hStdOutput = WritePipe;
Start.hStdInput = ReadPipe;
Start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
Start.wShowWindow = SW_HIDE;

if (CreateProcess(NULL, AppName.c_str(), &Security, &Security, true, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, NULL, NULL, &Start, &ProcessInfo))
{
do
{
Apprunning = WaitForSingleObject(ProcessInfo.hProcess, 100);
Application->ProcessMessages();
// вычитываем данные работающей консоли
do
{
Result = PeekNamedPipe(ReadPipe, NULL, 0, NULL, (LPDWORD) &DataSize, NULL);
if ((Result) && (DataSize))
{
if (DataSize > READ_BUFFER_SIZE) DataSize = READ_BUFFER_SIZE;
ReadFile(ReadPipe, Buffer, DataSize, &BytesRead, NULL);
Buffer[BytesRead] = 0;
OemToAnsi(Buffer, Buffer);
Memo->Text = Memo->Text + (AnsiString) Buffer;
}
}
while ((Result) && (DataSize));
}
while (Apprunning == WAIT_TIMEOUT);
}

delete [] Buffer;

CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ReadPipe);
CloseHandle(WritePipe);
}
}
 
R

rrrFer

Гость
#2
когда приложение выводит что-то в консоль - оно пишет в stdout.
Получить эти данные можно используя конвейер и перенаправление вывода, например (сходу я другие варианты не расскажу).

Не подойдет?

И я не понял как одновременно "в реальном времени" и "только после..."
 
09.08.2013
5
0
#3
Программа работает, но не так как нужно, она выдает результат консоли в memo только после завершения консольного приложения, а мне нужно как только что-то появилось в консоли сразу выводить в memo.

Я не совсем понял, есть консольная программа она выдает лог в консоль через stdout, мне нужно перехватить вывод в memo моей программы.
 
R

rrrFer

Гость
#4
я бы использовал конвейер если есть возможность.
консольная программа - p1, оконная - p2

запускай их следующим образом
./p1 | ./p2

при этом p1 пишет данные в stdout, а p2 читает их с stdin.

Пример с коленки:
Код:
#include <iostream>
#include <string>
int main() {
std::string buff;
for (int i = 0; i < 200; ++i) {
std::cin >> buff;
std::cerr << "[CERR] read: " << buff << "\n";
}
}
Код:
#include <iostream>
int main() {
for (int i = 0; i < 200; ++i) {
std::cout << i << "\n";
std::cerr << "[CERR] write: " << i << "\n";
}
}
Запускаешь как показано выше и наблюдаешь на экране (сообщения выводятся не в stdout а в stderr) картинку параллельной работы 2 приложений (читают и пишут они вперемешку). Под linux точно работает верно, но под windows хз (там тоже работают конвейеры, это точно, но статья на вики почему то помечена тегом [unix]: http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%...%80_%28UNIX%29).

Ну тока в твоем случае не в cerr выводить надо, а в мемо - я хз как это делается (твой код мне не понятен сходу).

-----------
либо, как я писал выше, можешь перенаправить вывод консольного приложения в файл (при помощи >> - тогда файл будет дописываться), а оконным - читать этот файл (разница вобщем не большая - читать файл или с stdin как в прошлом примере, но ты сможешь запустить консольное приложение из оконного {в твоем коде мне кажется так и делается}).
 
R

rrrFer

Гость
#6
1) Как вам + тыкнуть к репе.
под аватаркой плюсик, не найдешь - не беда )
2)Это не совсем то что мне нужно, консольное приложение сторонние, не имеет исходного кода.
исходный код тут не при чем. Оно пишет в stdin? - если да - то это то что нужно.

Допустим p2 принимает данные до тех пор, пока они там есть:
Код:
#include <iostream>
#include <string>
int main() {
std::string buff;
while (false == std::cin.eof()) {
std::cin >> buff;
std::cerr << "[CERR] read: " << buff << "\n";
}
}
В качестве p1 может быть что угодно (то, исходного кода чего у нас точно нет).
Я могу вызвать хоть
ls | ./p2
хоть
man | ./p2
разницы нет - запускаются 2 процесса, и поток вывода первого подается на вход потока ввода второго. Ты пишешь второй (который читает данные).
 
09.08.2013
5
0
#7
Хорошо, а если окон несколько? Вот вам пример чего я хочу, в архиве исходник, сама программа и тестовый hello world, Project1.exe - программа, 1.exe - "Привет мир" закрывается сам через 5 секунд, запускаете Project1.exe жмете на кнопку, программа запустит, 1.exe ждете 5 секунд, в основной программе появиться текст, после того как 1.exe закроется, а мне нужно как только запустилась 1.exe сразу печатать инфу из консоли в memo. Не уверен что понятно объяснил.
 

Вложения

R

rrrFer

Гость
#8
У меня линукс - не запустится ваш файл.
Вы пишите много букв, но мало кода (кроме кода с первого поста, который вы нашли где-то в интернете, и ваще код кривой).
Пишите код и указывайте чем он не подходит или озвучьте цену и укажите четкие требования.
Мне кажется, вы решили не разбираться с вариантами и ждете готовый код.