2008-11-19 7 views
7

Как запустить приложение и захватить вывод через stdout и, возможно, stderr?Запуск приложения, захват stdout и stderr в C++

Я пишу автоматизированную систему сборки, и мне нужно захватить вывод для анализа. Я хотел бы обновить репозиторий svn и захватить номер версии, чтобы я мог перемещать файлы в autobuild/revNumber/в случае успеха. Я также хотел бы построить с помощью make и загрузить компилируемый текст на свой сервер, чтобы все могли видеть предупреждения и ошибки при неудачной сборке.

Я не могу найти функцию system(), но я нашел функцию CreateProcess() на MSDN. Я могу запустить то, что мне нужно, но я не знаю, как захватить stderr и stdout. Я замечаю, что процесс запускается отдельно, если я не установил точку останова и не оставил приложение, которое затем сохранит весь текст в окне консоли приложения. Я также хотел бы подождать, пока все процессы не закончатся, а затем сканируют полученные данные для выполнения каких-либо дополнительных операций, которые мне нужны. Как мне это сделать?

ответ

11

В реальных оболочек (имеется в виду, а не морские раковины - я имею в виду, а не в C Shell или его производных), то:

program arg1 arg2 >/tmp/log.file 2>&1 

Это запускает программу с заданными аргументами, и перенаправляет стандартный вывод в/TMP /журнальный файл; обозначение (hieroglyph) '2>&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>&1' в созданной командной строке, чтобы отправить стандартную ошибку команды на то же место, что и стандартный вывод , но вам не понадобится временный файл:

После этого вы можете прочитать поток файлов. чистый способ сопоставить поток файлов C в C++ istream; вероятно, есть.

+0

Я считаю, что имя символа «&» является символом амперсанда. – 2009-06-12 18:00:43

4

Необходимо заполнить структуру 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); 

Я не показывал аспекты обработки ошибок, которые вам понадобятся. Пятый аргумент имеет значение true, чтобы наследовать дескрипторы. Другие объяснили, как создавать трубы, поэтому я не буду повторять его здесь.

0

ЭЛТ-компьютеры Microsoft и библиотека MSDN включают в себя системную функцию и функцию _popen.