2008-11-19 5 views
7

Wie starte ich eine app und erfassen die ausgabe über stdout und vielleicht stderr?starten app, capture stdout und stderr in C++

Ich schreibe ein automatisiertes Build-System und ich muss die Ausgabe erfassen, um zu analysieren. Ich möchte den SVN Repo aktualisieren und die Revisionsnummer holen, damit ich die Dateien in autobuild/revNumber/wenn erfolgreich verschieben kann. Ich möchte auch mit Make erstellen und den Kompilier-Text auf meinen Server hochladen, damit alle die Warnungen und Fehler bei einem fehlgeschlagenen Build sehen können.

Ich kann die system() Funktion nicht finden, aber ich fand die CreateProcess() Funktion auf MSDN. Ich bin in der Lage zu starten, was ich brauche, aber ich habe keine Ahnung, wie man die Stderr und Stdout erfassen. Ich stelle fest, dass der Prozess separat gestartet wird, es sei denn, ich setze einen Haltepunkt und halte meine App geschlossen. Dann behält sie den gesamten Text in meinem App-Konsolenfenster. Ich möchte auch warten, bis alle Prozesse abgeschlossen sind und dann die Daten scannen, um weitere Operationen durchzuführen, die ich brauche. Wie mache ich das?

Antwort

11

In echten Muscheln (was bedeutet, nicht Muscheln - ich meine, nicht in C-Shell oder seine Derivate), dann gilt:

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

Dies läuft Programm mit den angegebenen Argumenten, und leitet den stdout/tmp /Logdatei; Die Notation ( Hieroglyphe) '2>&1' am Ende sendet stderr (Dateideskriptor 2) an die gleiche Stelle, an der stdout (Dateideskriptor 1) geht. Beachten Sie, dass die Reihenfolge der Operationen wichtig ist; Wenn Sie sie umkehren, wird der Standardfehler an die Standardausgabe weitergeleitet, und dann wird die Standardausgabe (aber kein Standardfehler) in die Datei umgeleitet.

Die Auswahl des angezeigten Dateinamens ist aus mehreren Gründen miserabel - Sie sollten dem Benutzer erlauben, das Verzeichnis zu wählen, und sollte wahrscheinlich die Prozess-ID oder den Zeitstempel im Dateinamen enthalten.

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

In C++ können Sie die system() Funktion (geerbt von C) Prozesse laufen verwenden. Wenn Sie den Dateinamen im C++ - Programm kennen müssen (plausibel), generieren Sie den Namen im Programm (strftime() ist Ihr Freund) und erstellen Sie die Befehlszeichenfolge mit diesem Dateinamen. (Genau genommen benötigen Sie auch getenv(), um $ TMPDIR zu erhalten, und die POSIX-Funktion , um die Prozess-ID zu erhalten, und dann können Sie das zweizeilige Shell-Skript simulieren (obwohl die verwendete PID dem C++ - Programm und nicht dem gestarteten Programm entspricht) Shell)

Sie könnten stattdessen die POSIX popen() Funktion verwenden, Sie müssten die '2>&1'-Notation in die Befehlszeichenfolge aufnehmen, die Sie erstellen, um den Standardfehler des Befehls an die gleiche Stelle wie die Standardausgabe zu senden , aber Sie würden keine temporäre Datei benötigen.

anschließend können Sie die Datei-Stream abzulesen ich bin nicht sicher, ob ein es saubere Möglichkeit, einen C-Datei-Stream in C++ iStream abzubilden; da ist es wahrscheinlich.

+0

Ich glaube, der Name des "&" Zeichen/Glyph ist das kaufmännische Und. –

+0

Einverstanden: aber ich meinte "2> & 1" als "Hieroglyphe" (was ich leicht zugeben werde, ist ein Missbrauch des Begriffs). –

+0

Ich denke, es wäre ein bisschen klarer, wenn Sie "2> & 1" als "Weiterleitung" anstatt als "Heroglyphe" bezeichnen würden. Jemand, der mit der ägyptischen Linguistik nicht vertraut ist und den Begriff auf Wikipedia sucht, könnte sehr verwirrt werden. :) –

4

Sie müssen die STARTUP_INFO Struktur füllen, die hStdInput, hStdOutput und hStdError hat. Denken Sie daran, Griffe bei CreateProcess zu erben.

Ich habe nicht gezeigt, die Fehlerbehandlung Aspekte, die Sie tun müssen. Das fünfte Argument wird auf "true" gesetzt, um die Handles zu erben. Andere haben erklärt, wie man Pfeifen herstellt, also werde ich es hier nicht wiederholen.

0

Microsofts CRTs und die MSDN-Bibliothek enthalten die Systemfunktion und die _popen-Funktion.

Verwandte Themen