запустить приложение, захватить stdout и stderr в c ++
Вопрос
Как мне запустить приложение и записать вывод через stdout и, возможно, stderr?
Я пишу автоматизированную систему сборки, и мне нужно записать результаты для анализа. Я хотел бы обновить репозиторий SVN и получить номер ревизии, чтобы я мог переместить файлы в autobuild / revNumber / в случае успеха. Я также хотел бы собрать с помощью make и загрузить текст компиляции на мой сервер, чтобы все могли видеть предупреждения и ошибки при неудачной сборке.
Я не могу найти функцию system ()
, но я обнаружил функцию CreateProcess ()
в MSDN. Я могу запустить то, что мне нужно, но я не знаю, как захватить stderr и stdout. Я замечаю, что процесс запускается отдельно, если я не установлю точку останова и продолжу выход из моего приложения, после чего он сохранит весь текст в окне консоли приложения. Я также хотел бы подождать, пока все процессы не будут завершены, а затем просканировать полученные данные, чтобы выполнить любые дополнительные операции, которые мне нужны. Как мне это сделать?
Решение
В реальных оболочках (то есть не в морских оболочках - я имею в виду, не в C Shell или его производных), то
program arg1 arg2 >/tmp/log.file 2>&1
Это запускает программу с заданными аргументами и перенаправляет стандартный вывод в /tmp/log.file; запись ( иероглиф ) ' 2 > & amp; 1
' в конце отправляет stderr (дескриптор файла 2) в то же место, куда идет stdout (дескриптор файла 1). Обратите внимание, что последовательность операций важна; если вы измените их, то стандартная ошибка будет идти туда, куда шел стандартный вывод, а затем стандартный вывод (но не стандартная ошибка) будет перенаправлен в файл.
Выбор отображаемого имени файла является ужасным по многим причинам - вы должны разрешить пользователю выбирать каталог и, возможно, включать в него имя процесса или отметку времени.
LOG=${TMPDIR:-/tmp}/log.$.$(date +%Y%m%d-%H%M%S)
program arg1 arg2 >$LOG 2>&1
В C ++ вы можете использовать функцию system ()
(унаследованную от C) для запуска процессов. Если вам необходимо знать имя файла в программе на C ++ (правдоподобно), то сгенерируйте имя в программе ( strftime ()
- ваш друг) и создайте командную строку с этим именем файла.
(Строго говоря, вам также нужно getenv ()
, чтобы получить $ TMPDIR, и функцию POSIX getpid ()
, чтобы получить идентификатор процесса, а затем вы можете смоделировать двухстрочный сценарий оболочки (хотя используемый PID относится к программе C ++, а не к запущенной оболочке).
Вместо этого вы можете использовать функцию POSIX popen ()
; вам нужно будет включить нотацию 2 > & amp; 1
в создаваемую вами командную строку, чтобы отправить стандартную ошибку команды в то же место, куда идет стандартный вывод, но вы бы этого не сделали нужен временный файл:
FILE *pp = popen("program arg1 arg2 2>&1", "r");
Затем вы можете прочитать поток файла. Я не уверен, есть ли чистый способ отобразить поток файлов C в istream C ++; там, вероятно, есть.
Другие советы
Вам необходимо заполнить структуру STARTUP_INFO, в которой есть hStdInput, hStdOutput и hStdError. Не забудьте наследовать дескрипторы при создании CreateProcess.
/* Assume you open a file handle or pipe called myoutput */
STARTUP_INFO si_startinfo;
ZeroMemory(&si_startinfo, sizeof(STARTUP_INFO));
si_startinfo.cb = sizeof(STARTUP_INFO);
si_startinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si_startinfo.hStdOutput = myoutput;
si_startinfo.hStdError = myoutput;
si_startifno.dwFlags != STARTF_USEHANDLES;
PROCESS_INFORMATION pi_procinfo;
ZeroMemory(&pi_procinfo, sizeof(PROCESS_INFORMATION);
CreateProcess(NULL, cmdline, NULL, NULL, true, 0, NULL, pathname, &si_startinfo, &pi_procinfo);
Я не показал аспекты обработки ошибок, которые вам нужно будет сделать. 5-й аргумент устанавливается в true, чтобы наследовать дескрипторы. Другие объясняли, как создавать трубы, поэтому я не буду повторять это здесь.
ЭЛТ Microsoft и библиотека MSDN включают в себя системную функцию и функцию _popen.