2008-11-19 18 views
7

¿Cómo puedo iniciar una aplicación y capturar la salida mediante stdout y quizás stderr?aplicación de inicio, capture stdout y stderr en C++

Estoy escribiendo un sistema de compilación automatizado y necesito capturar la salida para analizar. Me gustaría actualizar el repositorio svn y tomar el número de revisión para poder mover los archivos en autobuild/revNumber/si tiene éxito. También me gustaría construir usando make y subir el texto de compilación a mi servidor para que todos puedan ver las advertencias y errores en una compilación fallada.

No puedo encontrar la función system(), pero encontré la función CreateProcess() en MSDN. Puedo lanzar lo que necesito pero no tengo idea de cómo capturar stderr y stdout. Noto que el proceso se inicia por separado, a menos que establezca un punto de interrupción y mantenga mi aplicación abierta, que luego conservará todo el texto en la ventana de la consola de mi aplicación. También me gustaría esperar hasta que todos los procesos hayan finalizado y luego analizar los datos que produjo para hacer las operaciones adicionales que necesito. ¿Cómo hago algo de esto?

Respuesta

11

En conchas reales (es decir, no conchas de mar - quiero decir, no en C Shell o sus derivados), entonces:

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

Este programa se ejecuta con los argumentos dados, y redirige la salida estándar a/tmp /archivo de registro; la notación ( jeroglífico) '2>&1' al final envía stderr (descriptor de archivo 2) al mismo lugar donde está yendo stdout (descriptor de archivo 1). Tenga en cuenta que la secuencia de operaciones es importante; si los invierte, entonces el error estándar irá a donde estaba yendo la salida estándar, y luego la salida estándar (pero no el error estándar) se redireccionará al archivo.

La elección del nombre de archivo que se muestra es abismal por varias razones: debe permitir que el usuario elija el directorio y probablemente debe incluir la identificación del proceso o la marca de tiempo en el nombre del archivo.

LOG=${TMPDIR:-/tmp}/log.$$.$(date +%Y%m%d-%H%M%S) 
program arg1 arg2 >$LOG 2>&1 

En C++, puede utilizar la función system() (heredado de C) para ejecutar procesos. Si necesita saber el nombre del archivo en el programa C++ (plausible), genere el nombre en el programa (strftime() es su amigo) y cree la cadena de comando con ese nombre de archivo. (Estrictamente, también necesita getenv() para obtener $ TMPDIR, y la función POSIX getpid() para obtener la ID del proceso, y luego puede simular la secuencia de comandos de shell de dos líneas (aunque el PID utilizado sería del programa C++, no el shell).

En su lugar, podría utilizar la función POSIX popen(); Tendría que incluir la notación '2>&1' en la cadena de comandos que crea para enviar el error estándar del comando al mismo lugar que la salida estándar , pero no necesitaría un archivo temporal:

Puede leer la transmisión de archivos. No estoy seguro de si hay una Manera limpia de mapear una secuencia de archivo C en una istream de C++. Probablemente haya.

+0

Creo que el nombre del caracter "y"/glifo es el signo y. –

+0

De acuerdo: pero me refería a todos los '2> y 1' como el 'jeroglífico' (que, lo concederé fácilmente, es un uso indebido del término). –

+0

Creo que sería un poco más claro si te refieras a '2> & 1' como una 'redirección' en lugar de un 'heiroglyph'. Alguien que no esté familiarizado con la lingüística egipcia y vaya y busque el término en wikipedia podría confundirse mucho. :) –

4

Debe completar la estructura STARTUP_INFO, que tiene hStdInput, hStdOutput y hStdError. Recuerde heredar identificadores cuando crea 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); 

No he mostrado los aspectos de manejo de errores, que tendrá que hacer. El quinto argumento se establece en verdadero para heredar los identificadores. Otros han explicado cómo crear tuberías, así que no lo repetiré aquí.

0

Los CRT de Microsoft y la biblioteca de MSDN incluyen la función del sistema y la función _popen.

Cuestiones relacionadas