Ich suche nach einer Möglichkeit, die Ausgabe eines Befehls abzurufen, wenn dieser in einem C ++ - Programm ausgeführt wird. Ich habe system()
versucht, die Funktion zu verwenden, aber das wird nur einen Befehl ausführen. Hier ist ein Beispiel für das, wonach ich suche:
std::string result = system("./some_command");
Ich muss einen beliebigen Befehl ausführen und seine Ausgabe erhalten. Ich habe mir boost.org angesehen , aber ich habe nichts gefunden, was mir das gibt, was ich brauche.
/programming/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c
für eine Erweiterung der großartigen Antwort unten, die Methoden zumreturn code
stderr
stdout
Antworten:
Pre-C ++ 11 Version:
Ersetzen
popen
undpclose
mit_popen
und_pclose
für Windows.quelle
result += buffer
, sodass das Rohr möglicherweise nicht richtig geschlossen wird.int main(){ puts("ERROR"); }
.Fehler- und Standardausgaben immer (und auch stdin schreiben, hier nicht dargestellt) ist leicht peasy mit meinem pstreams Header, der definierten Klassen iostream , dass die Arbeit wie
popen
:quelle
popen
Wenn Sie die C stdio-API verwenden müssen, bevorzuge ich die iostreams-API.popen
erfordert, dass Sie denFILE
Griff manuell bereinigen , pstreams tun dies automatisch. Akzeptiertpopen
nur einconst char*
für das Argument, das Sorgfalt erfordert, um Shell-Injection-Angriffe zu vermeiden. Mit pstreams können Sie einen Vektor mit ähnlichen Zeichenfolgen übergebenexecv
, was sicherer ist.popen
gibt dir nichts als eine Pipe, pstreams sagt dir die PID des Kindes, so dass du Signale senden kannst, z. B. um es zu töten, wenn es blockiert ist oder nicht beendet wird. All dies sind Vorteile, auch wenn Sie nur unidirektionale E / A möchten.pstreambuf::in_avail()
und daher nicht blockiert. Dies ermöglicht das Demultiplexen von stdout und stderr des Prozesses, da jeweils Daten verfügbar sind.pstreambuf::in_avail()
funktioniert nur zu 100% zuverlässig, wenn das Betriebssystem das nicht standardmäßige FIONREAD ioctl unterstützt, dies wird jedoch (zumindest) unter GNU / Linux und Solaris unterstützt.Ich würde popen () (++ waqas) verwenden .
Aber manchmal muss man lesen und schreiben ...
Es scheint, als würde niemand mehr auf die harte Tour gehen.
(Angenommen, eine Unix / Linux / Mac-Umgebung oder Windows mit einer POSIX-Kompatibilitätsschicht ...)
Möglicherweise möchten Sie auch mit select () und nicht blockierenden Lesevorgängen herumspielen.
quelle
execlp
Aufruf hat einen Fehler: Der letzte übergebenearg
Zeiger muss sein,(char *) NULL
um die Liste der variadischen Argumente ordnungsgemäß zu beenden (sieheexeclp(3)
Referenz).Funktioniert auch unter Windows,
popen
öffnet jedoch ein Konsolenfenster, das schnell über Ihre UI-Anwendung blinkt. Wenn Sie ein Profi sein möchten, ist es besser, dieses "Blinken" zu deaktivieren (insbesondere wenn der Endbenutzer es abbrechen kann).Also hier ist meine eigene Version für Windows:
(Dieser Code ist teilweise aus Ideen in The Code Project- und MSDN-Beispielen neu kombiniert .)
quelle
wchar_t
undCreateProcessW
als unnötige Einschränkung betrachte.The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Daher ist es möglicherweise besser, die Befehlszeile zuerst in einen separaten Puffer zu kopieren, um zu verhindern, dass der Aufrufer seine ursprüngliche Eingabe ändert.Zwei mögliche Ansätze:
Ich denke nicht, dass
popen()
es Teil des C ++ - Standards ist (es ist Teil von POSIX aus dem Speicher), aber es ist auf jedem UNIX verfügbar, mit dem ich gearbeitet habe (und Sie scheinen auf UNIX abzuzielen, da Ihr Befehl lautet./some_command
).Wenn dies nicht der Fall ist
popen()
, können Siesystem("./some_command >/tmp/some_command.out");
die Ausgabedatei mit den normalen E / A-Funktionen verarbeiten.quelle
Ich konnte nicht herausfinden, warum popen / pclose in Code :: Blocks fehlt / MinGW . Also habe ich das Problem umgangen, indem ich stattdessen CreateProcess () und CreatePipe () verwendet habe.
Hier ist die Lösung, die für mich funktioniert hat:
quelle
CREATE_NO_WINDOW
Ding vorbei?ListStdErr
wird nie benutzt.Das Folgende könnte eine tragbare Lösung sein. Es folgt Standards.
quelle
tmpnam
ist gefährlich, bessere Verwendungmkstemp
"Angenommen, POSIX, einfacher Code zum Erfassen von stdout:
Code-Beiträge sind für weitere Funktionen willkommen:
https://github.com/ericcurtin/execxx
quelle
Sie können die Ausgabe erhalten, nachdem Sie ein Skript mit einer Pipe ausgeführt haben. Wir verwenden Pipes, wenn wir die Ausgabe des untergeordneten Prozesses wünschen.
Hier ist also das Skript, das Sie ausführen möchten. Fügen Sie es in eine Befehlsvariable mit den Argumenten ein, die Ihr Skript akzeptiert (nichts, wenn keine Argumente). Und die Datei, in der Sie die Ausgabe des Skripts erfassen möchten, legen Sie sie in copy_fp ab.
Der Popen führt also Ihr Skript aus und legt die Ausgabe in fpipe ab. Anschließend können Sie einfach alles davon in Ihre Ausgabedatei kopieren.
Auf diese Weise können Sie die Ausgaben untergeordneter Prozesse erfassen.
Und ein anderer Prozess ist, dass Sie das direkt setzen können
>
Operator nur in den Befehl einfügen können. Wenn wir also alles in eine Datei einfügen, während wir den Befehl ausführen, müssen Sie nichts kopieren.In diesem Fall müssen keine Rohre verwendet werden. Sie können just verwenden
system
, und es wird der Befehl ausgeführt und die Ausgabe in diese Datei gestellt.Weitere Informationen finden Sie im YoLinux-Lernprogramm: Fork- , Exec- und Prozesssteuerung .
quelle
Beachten Sie, dass Sie eine Ausgabe erhalten können, indem Sie die Ausgabe in die Datei umleiten und dann lesen
Es wurde in der Dokumentation von gezeigt
std::system
Sie können den Exit-Code erhalten, indem Sie das
WEXITSTATUS
Makro aufrufen .quelle