app lançamento, stdout captura e stderr em c ++
Pergunta
Como faço para lançar um app e capturar a saída via stdout e talvez stderr?
Eu estou escrevendo um sistema de compilação automatizada e eu preciso para capturar a saída para analisar. Eu gostaria de atualizar o svn repo e pegue o número de revisão para que eu possa mover os arquivos em AutoBuild / revNumber / se bem sucedida. Eu também gostaria de construir usando marca e fazer o upload do texto de compilação para o meu servidor para que todos possam ver os avisos e erros em uma compilação falhou.
Não consigo encontrar a função system()
, mas eu achei a função CreateProcess()
no MSDN. Eu sou capaz de lançar o que eu preciso, mas não tenho idéia de como capturar o stderr e stdout. Eu observo os lançamentos de processo separadamente a menos que eu definir um ponto de interrupção e manter meu aplicativo Sair do qual, em seguida, vai manter todo o texto na minha janela do console aplicativo. Eu também gostaria de esperar até que todos os processos são terminou e, então, verificar os dados que produziu a fazer quaisquer operações adicionais que eu preciso. Como posso fazer nada disso?
Solução
Em escudos reais (ou seja, não conchas do mar - Quero dizer, não em C Shell ou seus derivados), então:
program arg1 arg2 >/tmp/log.file 2>&1
Este é executado programa com os argumentos dados e redireciona o stdout para /tmp/log.file; a notação ( hieróglifo ) '2>&1
' no final envia stderr (descritor de arquivo 2) para o mesmo lugar que stdout (descritor de arquivo 1) está indo. Note-se que a sequência de operações é importante; se você invertê-los, então o erro padrão irá para onde a saída padrão foi indo, e de saída, em seguida, padrão (mas não o erro padrão) será redirecionado para o arquivo.
A escolha do nome do arquivo mostrado é abismal por inúmeras razões -. Você deve permitir que o usuário escolha o diretório e, provavelmente, deve incluir o ID do processo ou data e hora no nome do arquivo
LOG=${TMPDIR:-/tmp}/log.$$.$(date +%Y%m%d-%H%M%S)
program arg1 arg2 >$LOG 2>&1
Em C ++, você pode usar a função system()
(herdado de C) para executar processos. Se você precisa saber o nome do arquivo no C ++ programa (plausível), em seguida, gerar o nome do programa (strftime()
é seu amigo) e criar a cadeia de comando com o nome do arquivo.
(Estritamente, você também precisa getenv()
para obter $ TMPDIR, ea função getpid()
POSIX para obter o ID do processo, e então você pode simular o script shell de duas linhas (embora o PID usado seria do programa C ++, não o shell lançado ).
Você pode sim usar a função POSIX popen()
; você teria que incluir o '2>&1
' notação na cadeia de comando que você cria para enviar o erro padrão do comando para o mesmo lugar como saída padrão vai, mas você não precisa de um arquivo temporário:
FILE *pp = popen("program arg1 arg2 2>&1", "r");
Você pode, então, lido no fluxo de arquivo. Eu não tenho certeza se há uma maneira limpa para mapear um fluxo de arquivo C em istream um C ++; provavelmente existe.
Outras dicas
Você precisa preencher a estrutura STARTUP_INFO, que tem hStdInput, hStdOutput e hStdError. Lembre-se de alças herdar quando você 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);
Eu não mostrei o erro de manipulação aspectos que você precisa fazer. A 5ª argumento é definido como verdadeiro para herdar as alças. Outros têm explicou como criar tubulações por isso não vou repeti-lo aqui.
CRTs da Microsoft e da biblioteca MSDN não incluem a função do sistema ea função _popen.