2008-11-19 18 views
7

Jak uruchomić aplikację i przechwycić wyjście przez stdout i może stderr?uruchomienie aplikacji, przechwytywanie stdout i stderr w C++

Piszę zautomatyzowany system kompilacji i potrzebuję przechwycić dane wyjściowe do analizy. Chciałbym zaktualizować repozytorium svn i pobrać numer wersji, aby móc przenieść pliki w autobuild/revNumber /, jeśli się powiedzie. Chciałbym również zbudować przy użyciu make i przesłać tekst kompilacji na mój serwer, aby wszyscy zobaczyli ostrzeżenia i błędy w nieudanej kompilacji.

Nie mogę znaleźć funkcji system(), ale znalazłem funkcję CreateProcess() na MSDN. Jestem w stanie uruchomić to, czego potrzebuję, ale nie mam pojęcia, jak uchwycić stderr i stdout. Zauważam, że proces uruchamia się osobno, chyba że ustawię punkt przerwania i będę wyłączał moją aplikację, a następnie zachowa cały tekst w oknie mojej aplikacji. Chciałbym również poczekać, aż wszystkie procesy zostaną zakończone, a następnie przeskanować dane, które zostały wykonane, aby wykonać dodatkowe operacje, których potrzebuję. Jak mogę to zrobić?

Odpowiedz

11

W prawdziwych muszli (to znaczy, nie muszelki - To znaczy, nie w C Shell lub jego pochodne), a następnie:

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

To prowadzi program z podanych argumentów i przekierowuje stdout do/tmp /plik dziennika; notacja ( hieroglyph) "2>&1" na końcu wysyła stderr (deskryptor 2 pliku) w to samo miejsce, w którym zmierza stdout (deskryptor pliku 1). Zwróć uwagę, że kolejność operacji jest ważna; jeśli je odwrócisz, to standardowy błąd przejdzie do miejsca, w którym działało standardowe wyjście, a następnie standardowe wyjście (ale nie standardowy błąd) zostanie przekierowane do pliku.

Wybór wyświetlanej nazwy pliku jest fatalny z wielu powodów - należy zezwolić użytkownikowi na wybranie katalogu i prawdopodobnie powinien zawierać identyfikator procesu lub sygnaturę czasową w nazwie pliku.

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

W C++ można użyć funkcji system() (dziedziczona z klasy C), aby uruchomić procesy. Jeśli potrzebujesz znać nazwę pliku w programie C++ (wiarygodne), wygeneruj nazwę w programie (strftime() jest twoim przyjacielem) i utwórz ciąg poleceń z tą nazwą pliku. (Ściśle, potrzebujesz również getenv(), aby uzyskać $ TMPDIR, i funkcję POSIX getpid(), aby uzyskać identyfikator procesu, a następnie możesz zasymulować dwu-liniowy skrypt powłoki (chociaż użyty PID byłby z programu C++, a nie uruchamiany powłoka):

Zamiast tego można użyć funkcji POSIX popen(), należy wpisać notację "2>&1" w ciągu polecenia, który utworzysz, aby wysłać standardowy błąd polecenia w to samo miejsce, co standardowe wyjście , ale nie potrzebujesz pliku tymczasowego:

Możesz następnie odczytać strumień plików. Nie jestem pewien, czy istnieje czysty sposób na mapowanie strumienia plików C do C++; tam prawdopodobnie jest.

+0

Wierzę, że nazwa "&" znaków/glifów to znak ampersand. –

+0

Zgadzam się: ale ja odnosiłem się do wszystkich "2> i 1" jako "hieroglifów" (co, z łatwością daję, jest niewłaściwym użyciem tego terminu). –

+0

Myślę, że byłoby to trochę bardziej jasne, gdybyś odniósł się do "2> i 1" jako "przekierowania" zamiast "heiroglifu". Ktoś, kto nie jest zaznajomiony z egipskim językoznawstwem, idzie i szuka terminu na wikipedii, może się bardzo zdezorientować. :) –

4

Musisz wypełnić strukturę STARTUP_INFO, która ma hStdInput, hStdOutput i hStdError. Pamiętaj, aby dziedziczyć uchwyty podczas 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); 

Nie pokazałem aspektów obsługi błędów, które należy wykonać. Piąty argument jest ustawiony na true, aby dziedziczyć uchwyty. Inni wyjaśnili, jak tworzyć rury, więc nie będę tego tutaj powtarzać.

0

Kody CRT firmy Microsoft i biblioteka MSDN zawierają funkcję systemową i funkcję _popen.

Powiązane problemy