Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Редирект потока вывода. Давайте пощупаем stdout  (Прочитано 386 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Boriska
Постоялец

ua
Offline Offline

« : 19-07-2019 11:26 » 

Привет коллеги.

Вот захотелось вывод одной консоли перебросить на другую консоль.
Тыкался мыкался, читал, в результате перебросил вывод одной консоли в файл в другом процессе.
Вот код.
Код: (C++)
int main()
{
        SECURITY_ATTRIBUTES sa;
        sa.nLength = sizeof(sa);
        sa.lpSecurityDescriptor = NULL;
        sa.bInheritHandle = TRUE;

        HANDLE h = CreateFile(L"out.log",
                FILE_APPEND_DATA,
                FILE_SHARE_WRITE | FILE_SHARE_READ,
                &sa,
                OPEN_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL);

        PROCESS_INFORMATION pi;
        STARTUPINFO si;
        BOOL ret = FALSE;

        DWORD No_Window_FLAG = CREATE_NO_WINDOW;
        DWORD With_Window_FLAG = CREATE_NEW_CONSOLE;

        HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE); //здесь я попытался получить хендл стандартного потока вывода

        ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
        ZeroMemory(&si, sizeof(STARTUPINFO));

        si.cb = sizeof(STARTUPINFO);
        si.dwFlags |= STARTF_USESTDHANDLES;
        si.hStdInput = NULL;
        si.hStdError = h;
        si.hStdOutput = h;
        //si.hStdOutput = hstdout; //тут попытался сделать вывод на консоль но не работает

        TCHAR cmd[] = L"CGIScript.exe";
        ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, With_Window_FLAG, NULL, NULL, &si, &pi);
               
        int t;
        std::cin >> t;

        if (ret)
        {
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
                return 0;
        }

        return -1;
}
вывод в файл работает, а вот вывод в консоль не работает наверное потому что я толком не дуплюсь что такое stdout и как работать с ним через handle
кстати на С# тут же накропал, все работает, но понятия мне не добавило
Код: (C#)
class Program
    {
        static void Main(string[] args)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo("CGIScript.exe");
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.RedirectStandardError = false;
            startInfo.WindowStyle = ProcessWindowStyle.Normal;
            Process process = Process.Start(startInfo);

            StreamReader outputReader = process.StandardOutput;
            StreamReader errorReader = process.StandardError;

            string line;
            while ((line = outputReader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }

            Console.ReadKey();
        }
    }
}
в С# все работает, но есть нюанс окно дочерней консоли не выводится, не понял почему.
« Последнее редактирование: 19-07-2019 13:02 от Boriska » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 19-07-2019 14:15 » 

Не совсем понятно, что ты именно хочеш получить. Типа Unix конвееров?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 19-07-2019 14:36 » 

Ключевое слово pipe (однонаправленный поток). Он имеет два конца: для записи и для чтения. Handle записи ставить как stdout одному процессу, handle чтения ставишь как stdin другому процессу. Запускаешь оба и ждешь их завершения. Даже перекачивать ничего не надо.

Но эта фраза непонятна:
Цитата
вывод одной консоли перебросить на другую консоль
Что ты имеешь в виду под консолью?
« Последнее редактирование: 19-07-2019 14:41 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Boriska
Постоялец

ua
Offline Offline

« Ответ #3 : 19-07-2019 17:18 » 

Имею ввиду обычное консольное приложение(проект).
Я так понял pipe это еще один способ. Я же вот назначил дочернему процессу хендл файла на поток вывода и он туда все слил (без перекачек). Но это в файл, а на экран(консоль) не получилучается.
Я же полагаю тот код который у меня работает на шарпе можно же как-то отобразить на С.

Добавлено через 2 минуты и 7 секунд:
Цитата
Не совсем понятно, что ты именно хочеш получить. Типа Unix конвееров?
Просто хочу из одного консольного приложения передать на экран(консоль) второго, типа как я сделал в шарповом примере.
« Последнее редактирование: 19-07-2019 17:27 от lkote » Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #4 : 23-07-2019 06:17 » new

у меня получилось что-то вроде такого:
Код: (C++)
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <windows.h>
#include <iostream.h>

int main(int argc, char* argv[])
{
        SECURITY_ATTRIBUTES sa;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;

        ZeroMemory(&pi, sizeof(pi));
        int t = 0;
        HANDLE in, out;
        BOOL rez;

        // создаём pipe
        ZeroMemory(&sa, sizeof(sa));
        sa.nLength = sizeof(sa);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
        rez = CreatePipe(&in, &out, &sa, 4096);

        // назначаем себе в качестве стандартного ввода
        CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
        // синхронизация с stdio/iostream
        rez = SetStdHandle(STD_INPUT_HANDLE, in);
        t = _open_osfhandle((long)in, _O_TEXT);
        *stdin = *_fdopen(t, "rt");
       
        // назначаем дочернему процессу в качестве стандартного вывода
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(STARTUPINFO);
        si.dwFlags |= STARTF_USESTDHANDLES;
        si.hStdInput = NULL;
        si.hStdError = si.hStdOutput = out;

        ios::sync_with_stdio();

        if (CreateProcess(NULL, "qq.exe", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
        {
          while (TRUE)
          {
            // читаем свой стандартный ввод
            cin >> t;
            // выводим полученное значение
            cout << t << endl;
          }
          return 0;
        }

        return 1;
}
Скорее всего можно было-бы сделать проще, если пытаться использовать stdio (printf()/fgets()), а не iostream(cin/cout).

Исходный текст программы qq.exe:
Код: (C++)
#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{ unsigned int i = 0;
  while (1)
  { printf("%u\n", i++);
    fflush(stdout);
    Sleep(100);
  }
  return 0;
}
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines