Перенаправление сообщений из консоли приложения в свою
От: _agg  
Дата: 12.10.18 09:49
Оценка:
Всем привет, есть небольшая консольная утилитка 1 которая запускает другую консольную утилитку 2, все работает кроме того что утилитка 2 пишет себе в консоль, а в консоль утилитки 1 эти сообщения не попадают, как заставить утилитку 2 писать сообщения в консоль утилитки 1.
Спасибо.
Re: Перенаправление сообщений из консоли приложения в свою
От: Maniacal Россия  
Дата: 12.10.18 10:29
Оценка:
Здравствуйте, _agg, Вы писали:

_>Всем привет, есть небольшая консольная утилитка 1 которая запускает другую консольную утилитку 2, все работает кроме того что утилитка 2 пишет себе в консоль, а в консоль утилитки 1 эти сообщения не попадают, как заставить утилитку 2 писать сообщения в консоль утилитки 1.

_>Спасибо.

В c/c++ можно тупо использовать popen и выводить полученный поток в свою консоль. А так, большинство консольных функций платформозависимы. В WinAPI в CreateProcess, например, можно указать свой HANDLE для stdin/stdout/stderr для запускаемого приложения.
Re: Перенаправление сообщений из консоли приложения в свою
От: CEMb  
Дата: 15.10.18 03:44
Оценка:
Здравствуйте, _agg, Вы писали:

_>Всем привет, есть небольшая консольная утилитка 1 которая запускает другую консольную утилитку 2, все работает кроме того что утилитка 2 пишет себе в консоль, а в консоль утилитки 1 эти сообщения не попадают, как заставить утилитку 2 писать сообщения в консоль утилитки 1.

_>Спасибо.

Поиском не нашёл, но примерно так: создаются пайпы для ввода-вывода и передаются в CreateProcess

  code
                SECURITY_ATTRIBUTES sa = { 0 };
                sa.nLength = sizeof(SECURITY_ATTRIBUTES);
                sa.lpSecurityDescriptor = NULL;
                sa.bInheritHandle = TRUE;

                HANDLE hChildStdoutRead = nullptr;
                HANDLE hChildStdoutWrite = nullptr;
                HANDLE hChildStdoutReadDup = nullptr;
                if (!CreatePipe(&hChildStdoutRead, &hChildStdoutWrite, &sa, 0))
                               return 1;

                BOOL bRet = DuplicateHandle(GetCurrentProcess(), hChildStdoutRead, GetCurrentProcess(), &hChildStdoutReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                if (!bRet)
                               return 1;
                CloseHandle(hChildStdoutRead);

                HANDLE hChildStdinRead = nullptr;
                HANDLE hChildStdinWrite = nullptr;
                HANDLE hChildStdinWriteDup = nullptr;
                if (!CreatePipe(&hChildStdinRead, &hChildStdinWrite, &sa, 0))
                               return 1;

                bRet = DuplicateHandle(GetCurrentProcess(), hChildStdinWrite, GetCurrentProcess(), &hChildStdinWriteDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
                if (!bRet)
                               return 1;
                CloseHandle(hChildStdinWrite);

                PROCESS_INFORMATION pi = { 0 };
                STARTUPINFO si = { 0 };
                si.cb = sizeof STARTUPINFO;
                si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
                si.hStdInput = hChildStdinRead;
                si.hStdOutput = hChildStdoutWrite;
                si.hStdError = hChildStdoutWrite;
                si.wShowWindow = SW_SHOW;

                LCID lcid = GetThreadLocale();
                SetThreadLocale(MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT), SORT_DEFAULT));

                CPINFOEX cpi = {0};
                GetCPInfoEx(CP_THREAD_ACP, 0, &cpi);

                BOOL bRes = CreateProcess(nullptr, lpCmdLine, nullptr, nullptr, TRUE, 0x0, nullptr, nullptr, &si, &pi);

Потом через ReadFile/WriteFile общается с пайпами в родительском процессе
Re[2]: Перенаправление сообщений из консоли приложения в свою
От: _agg  
Дата: 15.10.18 07:35
Оценка:
Не работает. Пытался запустить утилитку gpupdate /force что бы она мне в консоль писала инфу о своем состоянии.
Re[3]: Перенаправление сообщений из консоли приложения в свою
От: CEMb  
Дата: 16.10.18 03:29
Оценка: 14 (1)
Здравствуйте, _agg, Вы писали:

_>Не работает. Пытался запустить утилитку gpupdate /force что бы она мне в консоль писала инфу о своем состоянии.


Закинул сюда тестовый проект. VS 2013

В дебажной версии он запускает cmd.exe и перенаправляет его потоки на себя, создаёт консольное окно и всё, что вбивается внизу, скидывается во входящую пайпу cmd.exe, т.е. как будто вбивают напрямую там. А то, что cmd.exe отвечает — скидывается в консоль сверху.

  детали
ConsoleWnd — своё окно консоли
Dlg — обёртка под диалог
Main — там всё создаётся, запускается и привязывается, код оттуда я приводил выше
Re[4]: Перенаправление сообщений из консоли приложения в свою
От: _agg  
Дата: 16.10.18 06:38
Оценка:
Спасибо большое за проект, не просто какие то абстрактные ответы, а проект, спасибо.
Re[4]: Перенаправление сообщений из консоли приложения в свою
От: _agg  
Дата: 16.10.18 06:55
Оценка:
С вашим проектом сделал простую вещь в Debugging -> Command arguments подписал gpupdate /force. Запустилось 2 консоли, одна аля CMD с командной строкой, вторая с gpupdate /force причем gpupdate в свою консоль тоже ничего не написал... В общем пока результат не получил к сожалению, вроде простая же вещь, из своей консоли запускаю консольный процесс что бы запущенный консольный процесс писал сообщения в мою консоль.
Re[5]: Перенаправление сообщений из консоли приложения в свою
От: CEMb  
Дата: 16.10.18 08:06
Оценка:
Здравствуйте, _agg, Вы писали:

_>С вашим проектом сделал простую вещь в Debugging -> Command arguments подписал gpupdate /force. Запустилось 2 консоли, одна аля CMD с командной строкой, вторая с gpupdate /force причем gpupdate в свою консоль тоже ничего не написал... В общем пока результат не получил к сожалению, вроде простая же вещь, из своей консоли запускаю консольный процесс что бы запущенный консольный процесс писал сообщения в мою консоль.


я его делал для своих java-консолек, чтобы в "красивое" окно выводить. Т.е. при запуске в качестве параметра указывал java-приложение(как по аналогии в дебаге указан cmd.exe). Проект его стартовал и дальше с прогой на яве можно было общаться через моё окно.

Странно, что у тебя не работает Возможно gpupdate не пользуется стандартными потоками ввода-вывода?
Re[5]: Перенаправление сообщений из консоли приложения в свою
От: Maniacal Россия  
Дата: 16.10.18 13:52
Оценка:
Здравствуйте, _agg, Вы писали:

_>С вашим проектом сделал простую вещь в Debugging -> Command arguments подписал gpupdate /force. Запустилось 2 консоли, одна аля CMD с командной строкой, вторая с gpupdate /force причем gpupdate в свою консоль тоже ничего не написал... В общем пока результат не получил к сожалению, вроде простая же вещь, из своей консоли запускаю консольный процесс что бы запущенный консольный процесс писал сообщения в мою консоль.


Ну вот на коленке и без WinAPI с захардкоженным вызовом gpupdate пример:
#include <thread>
#include <stdio.h>

int main()
{
    std::thread lambda_thread([]() {
        FILE* f = _popen("gpupdate /force", "rt");
        char acBuffer[256];
        while (!feof(f))
        {
            memset(acBuffer, 0, sizeof(acBuffer));
            if (fread(acBuffer, 1, sizeof(acBuffer), f) > 0) printf(acBuffer);
            else break;
        }
        fclose(f);
    });
    getchar();
    lambda_thread.join();
}
Re[6]: Перенаправление сообщений из консоли приложения в свою
От: _agg  
Дата: 17.10.18 05:37
Оценка:
Век живи век учись даже не предполагал что так можно, спасибо :
#include <thread>
#include <stdio.h>

int main()
{
    std::thread lambda_thread([]() {
        FILE* f = _popen("gpupdate /force", "rt");
        char acBuffer[256];
        while (!feof(f))
        {
            memset(acBuffer, 0, sizeof(acBuffer));
            if (fread(acBuffer, 1, sizeof(acBuffer), f) > 0) printf(acBuffer);
            else break;
        }
        fclose(f);
    });
    getchar();
    lambda_thread.join();
}


Этот код работает, минус в том что если процесс нужно запускать от администратора с помощью CreateProcessAsUser тогда это не получиться
Re[7]: Перенаправление сообщений из консоли приложения в сво
От: Maniacal Россия  
Дата: 17.10.18 06:35
Оценка: 6 (1)
Здравствуйте, _agg, Вы писали:

_>Этот код работает, минус в том что если процесс нужно запускать от администратора с помощью CreateProcessAsUser тогда это не получиться

можно запустить строкой типа "runas /user:administrator /savecred gpupdate /force". Пароль спросит только один раз, потом запомнит.
Отредактировано 17.10.2018 6:40 Maniacal . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.