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

Тема в разделе "Borland C++ Builder & Kylix", создана пользователем updaite, 9 авг 2013.

  1. updaite

    updaite Member

    Регистрация:
    9 авг 2013
    Сообщения:
    5
    Симпатии:
    0
    Программа выводить текст с консоли в 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);
    }
    }
     
  2. rrrFer

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    когда приложение выводит что-то в консоль - оно пишет в stdout.
    Получить эти данные можно используя конвейер и перенаправление вывода, например (сходу я другие варианты не расскажу).

    Не подойдет?

    И я не понял как одновременно "в реальном времени" и "только после..."
     
  3. updaite

    updaite Member

    Регистрация:
    9 авг 2013
    Сообщения:
    5
    Симпатии:
    0
    Программа работает, но не так как нужно, она выдает результат консоли в memo только после завершения консольного приложения, а мне нужно как только что-то появилось в консоли сразу выводить в memo.

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

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    я бы использовал конвейер если есть возможность.
    консольная программа - p1, оконная - p2

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

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

    Пример с коленки:
    Код (Text):
    #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";
    }
    }
    Код (Text):
    #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 как в прошлом примере, но ты сможешь запустить консольное приложение из оконного {в твоем коде мне кажется так и делается}).
     
  5. updaite

    updaite Member

    Регистрация:
    9 авг 2013
    Сообщения:
    5
    Симпатии:
    0
    1) Как вам + тыкнуть к репе.
    2)Это не совсем то что мне нужно.
     
  6. rrrFer

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    под аватаркой плюсик, не найдешь - не беда )
    исходный код тут не при чем. Оно пишет в stdin? - если да - то это то что нужно.

    Допустим p2 принимает данные до тех пор, пока они там есть:
    Код (Text):
    #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 процесса, и поток вывода первого подается на вход потока ввода второго. Ты пишешь второй (который читает данные).
     
  7. updaite

    updaite Member

    Регистрация:
    9 авг 2013
    Сообщения:
    5
    Симпатии:
    0
    Хорошо, а если окон несколько? Вот вам пример чего я хочу, в архиве исходник, сама программа и тестовый hello world, Project1.exe - программа, 1.exe - "Привет мир" закрывается сам через 5 секунд, запускаете Project1.exe жмете на кнопку, программа запустит, 1.exe ждете 5 секунд, в основной программе появиться текст, после того как 1.exe закроется, а мне нужно как только запустилась 1.exe сразу печатать инфу из консоли в memo. Не уверен что понятно объяснил.
     

    Вложения:

    • consol.zip
      Размер файла:
      204,7 КБ
      Просмотров:
      3
  8. rrrFer

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    У меня линукс - не запустится ваш файл.
    Вы пишите много букв, но мало кода (кроме кода с первого поста, который вы нашли где-то в интернете, и ваще код кривой).
    Пишите код и указывайте чем он не подходит или озвучьте цену и укажите четкие требования.
    Мне кажется, вы решили не разбираться с вариантами и ждете готовый код.
     
Загрузка...

Поделиться этой страницей