Wie kann ich ein externes Programm von C ausführen und seine Ausgabe analysieren?
Lesezeit: 6 Minuten
Josh Matthews
Ich habe ein Dienstprogramm, das eine Liste von Dateien ausgibt, die von einem Spiel benötigt werden. Wie kann ich dieses Dienstprogramm in einem C-Programm ausführen und seine Ausgabe abrufen, damit ich im selben Programm darauf reagieren kann?
UPDATE: Guter Aufruf zum Mangel an Informationen. Das Dienstprogramm spuckt eine Reihe von Zeichenfolgen aus, die auf Mac/Windows/Linux portierbar sein sollen. Bitte beachten Sie, dass ich nach einer programmgesteuerten Möglichkeit suche, das Dienstprogramm auszuführen und seine Ausgabe beizubehalten (die an stdout geht).
siehe auch stackoverflow.com/questions/125828/…
– Rogerpack
25. September 2012 um 22:30 Uhr
Wenn Sie auch stderr wollen, können Sie umleiten, zum Beispiel rufen Sie ls nonexistant-name 2>&1 auf
– Vic
10. April 2013 um 3:11 Uhr
Dies ist kein Duplikat; Die verknüpfte Frage ist C++ spezifischwährend es bei dieser Frage darum geht C.
– Kyle Strand
22. März 2016 um 22:21 Uhr
Ich stimme dafür, diese Frage erneut zu öffnen, da es sich nicht um ein Duplikat handelt, sondern um C, nicht um C ++
– hasan
20. Juni 2017 um 9:51 Uhr
siehe auch stackoverflow.com/questions/9405985/…
– Munition Göttsch
3. September 2017 um 15:37 Uhr
MestreLion
Wie andere bereits betont haben, popen() ist der üblichste Weg. Und da keine Antwort ein Beispiel mit dieser Methode lieferte, hier geht es:
#include <stdio.h>
#define BUFSIZE 128
int parse_output(void) {
char *cmd = "ls -l";
char buf[BUFSIZE];
FILE *fp;
if ((fp = popen(cmd, "r")) == NULL) {
printf("Error opening pipe!\n");
return -1;
}
while (fgets(buf, BUFSIZE, fp) != NULL) {
// Do whatever you want here...
printf("OUTPUT: %s", buf);
}
if (pclose(fp)) {
printf("Command not found or exited with error status\n");
return -1;
}
return 0;
}
Beispielausgabe:
OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c
Sollte nicht if(pclose(fp)) sein if(pclose(fp) == -1)?
– Spikatrix
31. März 2016 um 9:03 Uhr
@CoolGuy: hängt davon ab, was Sie wollen. pclose() Rückkehr -1 wenn beim Abrufen des Exit-Status des Befehls ein Fehler aufgetreten ist, ansonsten wird der Exit-Status selbst zurückgegeben. Als Befehle setzen Sie traditionell den Exit-Status 0 um Erfolg anzuzeigen, durch Ankreuzen if(pclose(fp)) Wir testen beide auf Fehler pclose() oder der Befehl.
– MestreLion
31. März 2016 um 22:48 Uhr
Vielen Dank für dieses Beispiel, es leitet die Ausgabe eines anderen Programms an die Ausgabe des aktuellen Programms weiter. Vielen Dank!
– Jo
30. März 2019 um 0:20 Uhr
Ein weiteres Beispiel: Gibt es eine Möglichkeit, die Ausgabe eines Linux-Befehls (wie ifconfig) in einer .txt-Datei mit einem C-Programm zu erhalten?
– Gabriel Staples
9. Dezember 2021 um 6:31 Uhr
@GabrielStaples: fgets() eignet sich eher zum Lesen von Textausgaben als von binären, da es automatisch eine Zeile nach der anderen abruft und bei Zeilenumbrüchen aufteilt. Beides erfordert die while Schleife, da Sie nicht sicher sein können, dass die gesamte Ausgabe hineinpasst BUFSIZE.
– MestreLion
9. Dezember 2021 um 19:51 Uhr
dmckee — Ex-Moderator-Kätzchen
Bei einfachen Problemen in Unix-ähnlichen Umgebungen versuchen Sie es popen().
Aus der Manpage:
Die Funktion popen() öffnet einen Prozess, indem sie eine Pipe erstellt, die Shell verzweigt und aufruft.
Wenn Sie den Lesemodus verwenden, ist dies genau das, wonach Sie gefragt haben. Ich weiß nicht, ob es in Windows implementiert ist.
Für kompliziertere Probleme sollten Sie die Kommunikation zwischen Prozessen nachschlagen.
einige Beispiele für die richtige Verwendung popen() wäre nett.
– Alexej Magura
29. Juli 2013 um 19:29 Uhr
Ich habe einen Link zur Manpage Open Group für die Funktion hinzugefügt, der ein Beispiel enthält. Grundsätzlich popen bekommt man einen Dateizeiger sehr ähnlich fopen. Es ist nur so, dass Sie damit in die Standardeingabe schreiben oder von der Standardausgabe eines Programms lesen können, anstatt mit einer Festplattendatei zu interagieren. Das ist Unix „Alles ist eine Datei“ Philosophie am Werk. Einige Implementierungen erweitern den Standard, indem sie eine bidirektionale Kommunikation ermöglichen.
– dmckee — Ex-Moderator-Kätzchen
30. Juli 2013 um 1:09 Uhr
Darauf deutet diese Antwort hin popen ist unter Windows verfügbar.
– Jonathon Reinhart
25. Juni 2015 um 19:17 Uhr
Für die Lösung mit den Raw-Dateihandles (wenn Sie zum Beispiel asynchrone E/A benötigen) siehe stackoverflow.com/questions/9405985/…
Wenn Sie möchten, dass es plattformübergreifend ist, ist Popen der richtige Weg.
David J. Sokol
Angenommen, Sie befinden sich auf einer Befehlszeile in einer Windows-Umgebung, können Sie Pipes oder Befehlszeilenumleitungen verwenden. Zum Beispiel,
Innerhalb Ihres Programms könnten Sie die C-Standardeingabefunktionen verwenden, um die Ausgabe anderer Programme zu lesen (scanf usw.): http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp . Sie könnten auch das Dateibeispiel verwenden und fscanf verwenden. Dies sollte auch unter Unix/Linux funktionieren.
Dies ist eine sehr allgemeine Frage. Vielleicht möchten Sie weitere Details angeben, z. B. um welche Art von Ausgabe es sich handelt (nur Text oder eine Binärdatei?) Und wie Sie sie verarbeiten möchten.
Edit: Hurra Klarstellung!
Das Umleiten von STDOUT scheint mühsam zu sein, ich musste es in .NET tun, und es hat mir alle möglichen Kopfschmerzen bereitet. Es sieht so aus, als ob der richtige C-Weg darin besteht, einen untergeordneten Prozess zu erzeugen, einen Dateizeiger zu erhalten, und plötzlich tut mir der Kopf weh.
Hier ist also ein Hack, der temporäre Dateien verwendet. Es ist einfach, aber es sollte funktionieren. Dies funktioniert gut, wenn die Geschwindigkeit kein Problem darstellt (das Auftreffen auf die Festplatte ist langsam) oder wenn es weggeworfen wird. Wenn Sie ein Unternehmensprogramm erstellen, ist es wahrscheinlich am besten, sich die STDOUT-Umleitung anzusehen und zu verwenden, was andere Leute empfohlen haben.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE * fptr; // file holder
char c; // char buffer
system("dir >> temp.txt"); // call dir and put it's contents in a temp using redirects.
fptr = fopen("temp.txt", "r"); // open said file for reading.
// oh, and check for fptr being NULL.
while(1){
c = fgetc(fptr);
if(c!= EOF)
printf("%c", c); // do what you need to.
else
break; // exit when you hit the end of the file.
}
fclose(fptr); // don't call this is fptr is NULL.
remove("temp.txt"); // clean up
getchar(); // stop so I can see if it worked.
}
Stellen Sie sicher, dass Sie Ihre Dateiberechtigungen überprüfen: Im Moment wird die Datei einfach in dasselbe Verzeichnis wie eine EXE-Datei geworfen. Vielleicht möchten Sie sich mit der Verwendung befassen /tmp in nix, bzw C:\Users\username\Local Settings\Temp unter Vista, bzw C:\Documents and Settings\username\Local Settings\Temp in 2K/XP. Ich denke, die /tmp wird in OSX funktionieren, aber ich habe noch nie einen verwendet.
Unter Linux und OS X, popen() ist wirklich die beste Wahl, wie dmckee betonte, da beide Betriebssysteme diesen Aufruf unterstützen. Unter Windows sollte das helfen: http://msdn.microsoft.com/en-us/library/ms682499.aspx
Angus Conell
Laut MSDN-Dokumentation gibt die _popen-Funktion bei Verwendung in einem Windows-Programm einen ungültigen Dateizeiger zurück, der dazu führt, dass das Programm auf unbestimmte Zeit nicht mehr reagiert. _popen funktioniert ordnungsgemäß in einer Konsolenanwendung. Informationen zum Erstellen einer Windows-Anwendung, die Eingabe und Ausgabe umleitet, finden Sie unter Erstellen eines untergeordneten Prozesses mit umgeleiteter Eingabe und Ausgabe im Windows SDK.
JB.
Sie können verwenden system() wie in:
system("ls song > song.txt");
wo ls ist der Befehlsname zum Auflisten des Inhalts des Ordners song und song ist ein Ordner im aktuellen Verzeichnis. Resultierende Datei song.txt wird im aktuellen Verzeichnis erstellt.
Was ist, wenn ich die Ausgabe anderer Programme in eine Datei umleiten möchte? kein os-Befehl
– Amin Da.
17. April 2016 um 1:30 Uhr
Nein, das ist ein sehr schlechter Weg. Machen Sie es richtig mit Pipes, hinterlassen Sie keine temporären Dateien im gesamten Dateisystem.
– Eule
5. Oktober 2018 um 14:55 Uhr
14185100cookie-checkWie kann ich ein externes Programm von C ausführen und seine Ausgabe analysieren?yes
siehe auch stackoverflow.com/questions/125828/…
– Rogerpack
25. September 2012 um 22:30 Uhr
Wenn Sie auch stderr wollen, können Sie umleiten, zum Beispiel rufen Sie ls nonexistant-name 2>&1 auf
– Vic
10. April 2013 um 3:11 Uhr
Dies ist kein Duplikat; Die verknüpfte Frage ist C++ spezifischwährend es bei dieser Frage darum geht C.
– Kyle Strand
22. März 2016 um 22:21 Uhr
Ich stimme dafür, diese Frage erneut zu öffnen, da es sich nicht um ein Duplikat handelt, sondern um C, nicht um C ++
– hasan
20. Juni 2017 um 9:51 Uhr
siehe auch stackoverflow.com/questions/9405985/…
– Munition Göttsch
3. September 2017 um 15:37 Uhr