Wie kann ich ein externes Programm von C aus ausführen und seine Ausgabe analysieren?

StackOverflow https://stackoverflow.com/questions/43116

  •  09-06-2019
  •  | 
  •  

Frage

Ich habe ein Dienstprogramm, das eine Liste der für ein Spiel erforderlichen Dateien ausgibt.Wie kann ich dieses Dienstprogramm in einem C-Programm ausführen und seine Ausgabe abrufen, damit ich im selben Programm darauf reagieren kann?

AKTUALISIEREN:Guter Hinweis auf den Mangel an Informationen.Das Dienstprogramm gibt eine Reihe von Zeichenfolgen aus und soll vollständig auf Mac/Windows/Linux portierbar sein.Bitte beachten Sie, dass ich nach einer programmgesteuerten Möglichkeit suche, das Dienstprogramm auszuführen und seine Ausgabe beizubehalten (die an stdout geht).

War es hilfreich?

Lösung

Versuchen Sie es bei einfachen Problemen in Unix-Umgebungen popen().

Von der Manpage:

Die Funktion popen() öffnet einen Prozess, indem sie eine Pipe erstellt, eine Verzweigung durchführt und die Shell aufruft.

Wenn Sie den Lesemodus verwenden, ist dies genau das, wonach Sie gefragt haben.Ich weiß nicht, ob es in Windows implementiert ist.

Bei komplizierteren Problemen sollten Sie nach prozessübergreifender Kommunikation suchen.

Andere Tipps

Wie andere bereits betont haben, popen() ist der Standardweg.Und da keine Antwort ein Beispiel für diese Methode lieferte, hier:

#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;
}

popen wird unter Windows unterstützt, siehe hier:

http://msdn.microsoft.com/en-us/library/96ayss4b.aspx

Wenn Sie möchten, dass es plattformübergreifend ist, ist Popen die richtige Wahl.

Vorausgesetzt, Sie befinden sich in einer Windows-Umgebung in einer Befehlszeile, können Sie Pipes oder Befehlszeilenumleitungen verwenden.Zum Beispiel,

commandThatOutputs.exe > someFileToStoreResults.txt

oder

commandThatOutputs.exe | yourProgramToProcessInput.exe

Innerhalb Ihres Programms können Sie die C-Standardeingabefunktionen verwenden, um die Ausgabe anderer Programme (scanf usw.) zu lesen: http://irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output.asp .Sie können auch die Beispieldatei verwenden und fscanf verwenden.Dies sollte auch unter Unix/Linux funktionieren.

Dies ist eine sehr allgemeine Frage. Möglicherweise 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.

Bearbeiten:Hurra, Klarstellung!

Das Umleiten von STDOUT scheint mühsam zu sein, ich musste es in .NET machen und es bereitete mir allerlei Kopfschmerzen.Es sieht so aus, als ob der richtige C-Weg darin besteht, einen untergeordneten Prozess zu starten, 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 sie weggeworfen wird.Wenn Sie ein Unternehmensprogramm erstellen, ist es wahrscheinlich am besten, sich die STDOUT-Umleitung anzusehen und dabei die Empfehlungen anderer Leute zu verwenden.

#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.
}

Überprüfen Sie unbedingt Ihre Dateiberechtigungen:Im Moment wird die Datei dadurch einfach in dasselbe Verzeichnis wie eine Exe-Datei verschoben.Vielleicht möchten Sie die Verwendung in Betracht ziehen /tmp in nix, oder C:\Users\username\Local Settings\Temp in Vista, oder C:\Documents and Settings\username\Local Settings\Temp in 2K/XP.Ich denke der /tmp wird unter OSX funktionieren, aber ich habe noch nie eines verwendet.

Unter Linux und OS popen() ist wirklich die beste Wahl, wie dmckee betonte, da beide Betriebssysteme diesen Aufruf unterstützen.Unter Windows sollte dies helfen: http://msdn.microsoft.com/en-us/library/ms682499.aspx

In der MSDN -Dokumentation wird angegeben, dass die Funktion _popen einen ungültigen Dateizeiger zurückgibt, 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.

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.

//execute external process and read exactly binary or text output
//can read image from Zip file for example
string run(const char* cmd){
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[262144];
    string data;
    string result;
    int dist=0;
    int size;
    //TIME_START
    while(!feof(pipe)) {
        size=(int)fread(buffer,1,262144, pipe); //cout<<buffer<<" size="<<size<<endl;
        data.resize(data.size()+size);
        memcpy(&data[dist],buffer,size);
        dist+=size;
    }
    //TIME_PRINT_
    pclose(pipe);
    return data;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top