Forum: PC-Programmierung programmausgaben in string umleiten


von andre (Gast)


Lesenswert?

ich starte über ein c++ programm ein weiteres programm. dieses 
gestartete programm gibt fleissig output in die konsole. diesen output 
würde ich nun gerne in meinem programm als string verarbeiten.

welche möglichkeiten habe ich, den fremden konsolenouptut aufzufangen?

von Klaus W. (mfgkw)


Lesenswert?

Es gibt zum Einen die Möglichkeit, das Programm mit popen()
zu starten. Damit kann man wahlweise die Ein- oder die Ausgabe
umleiten.

Eine andere Variante, mit der beides gleichzeitig geht (und
vermutlich auch gleich stderr) ist es, das Programm mit system()
zu starten.
In der dort anzugebenden Kommandozeile kann man nach dem
Programmaufruf die Ein- und Ausgabe mit "... >&95 <&97"
mit Dateien verknüpfen, die im aufrufenden Prozeß die fd-Nummern
beispielsweise 95 und 97 haben.
Man öffnet also vorher die Dateien und trägt die fd-Nummern
mit sprintf() in die Kommandozeile ein.
Analog z.B. "... 2>&98 ..." für stderr (was mal unter
Windows 2000 bei mir geklappt hatte, unter XP irgendwann mal
nicht; ich habe es aber nicht weiter verfolgt).
Startet man das Programm zusätzlich mit einem & am Ende, kann
man während es läuft zu fd 97 etwas schreiben, was vom
Kindprozeß von stdin gelesen wird, und gleichzeitig von 95
bzw. 98 dessen Ausgabe lesen.

Dieser Weg ist etwas umständlicher, aber wesentlich flexibler.
Einfacher ist popen(), wenn es reicht.

von Sven H. (dsb_sven)


Lesenswert?

Ich gehe mal davon aus, dass du die Möglichkeit hast, den standard 
output deines Programms abzufangen. In C# gehts über die Klasse Process, 
wenn ich mich nicht irre...

von Klaus W. (mfgkw)


Lesenswert?

PS: es geht natürlich nur, wenn das Kind Standardein- und -ausgabe
verwendet.
Die Windows-eigenen Konsolenfunktionen lassen sich so nicht abfangen.

von Max (Gast)


Lesenswert?

Falls das Programm  myprog.exe ist:

In der Konsole

myprog >Dateiname

eingeben.

z.B.
dir >d.txr

von andre (Gast)


Lesenswert?

die sache verhält sich im detail folgendermaßen. ich nutze um das 
programm zu öffnen die pstream lib welche auf popen aufsetzt. 
(http://pstreams.sourceforge.net/)

öffne ich damit als beispiel ifconfig:
1
std::string s, ausgabe;
2
redi::pstream ifconfig("ifconfig -a");
3
while(std::getline(ifconfig, s)) {
4
   ausgabe.append(s);
5
   ausgabe.append("\n");
6
}
7
textview_buffer->set_text(ausgabe);

landet der konsolenoutput wunderbar im string ausgabe und wird meinem 
gtk widget zugefügt.

ich will aber nicht ifconfig anzeigen. mein programm startet ein android 
sdk tool welches unterschiedliche parameter hat. mit einem der parameter 
geht es. dieser parameter öffnet eine shell zum android device und ich 
kann problemlos infos hin und her schieben
1
std::string s, ausgabe;
2
chdir(path_to_adb.c_str());
3
redi::pstream adb_shell("./adb shell");
4
adb_shell << "mount /system" << std::endl;
5
adb_shell << "chmod 644 /system/app/*" << std::endl;
6
adb_shell << "chmod 644 /system/framework/*" << std::endl;
7
adb_shell << "exit" << std::endl;
8
while(std::getline(adb_shell, s)) {
9
   ausgabe.append(s);
10
   ausgabe.append("\n");
11
   }
12
textview_buffer->set_text(ausgabe);

folgende anweisung geht aber nicht. dieses mal wird keine shell geöffnet 
sondern durch das android tool der inhalt eines ordners datei für datei 
gepushed.
1
std::string s, ausgabe;
2
std::string system_app;
3
std::string copy_apps;
4
system_app = "ls ";          
5
system_app.append(path_to_binary);
6
system_app.append("/system/app/");
7
redi::ipstream ls(system_app);
8
while (ls >> copy_apps) { 
9
   chdir(path_to_adb.c_str());
10
   std::string command = "./adb push ";
11
   command.append(path_to_binary);
12
   command.append("/system/app/");
13
   command.append(copy_apps);
14
   command.append(" /system/app/");
15
   redi::pstream adb_push(command);
16
   while(std::getline(adb_push, s)) {
17
      ausgabe.append(s);
18
      ausgabe.append("\n");
19
   }
20
21
   textview_buffer->set_text(ausgabe);
22
}

der unterschied zwischen der 2. und 3. anweisung ist eigentlich nur der, 
das adb shell eine dauerhafte verbindung aufbaut in welche ich schreiben 
und lesen kann. adb push hält keine verbindung offen. es kopiert die 
datei und damit ist die sache abgeharkt. aber auch adb push gibt auf der 
konsole output über die kopierten daten und wie lange es gedauert hat. 
ich komme halt nur nicht ran.

von andre (Gast)


Lesenswert?

hier noch mal das letzte listing in übersichtlich und ohne unnötigen 
schnick schnack
1
std::string s, ausgabe;
2
chdir(path_to_adb.c_str());  
3
redi::pstream adb_pull("./adb pull /system/app /home/dir/");
4
while(std::getline(adb_pull, s)) {
5
  ausgabe.append(s);
6
  ausgabe.append("\n");
7
}
8
textview_buffer->set_text(ausgabe);

adb mit dem parameter pull gibt mir also über die pstream lib keinen 
output zurück. schiebt aber trotzdem output in die konsole.

von Klaus (Gast)


Lesenswert?

Du solltest mit etwas einfacherem anfangen! Wie wärs, wenn du dir als 
erstes Grundkenntnisse im Benutzen der Shift-Taste aneignest? Das übst 
du dann noch ein wenig, dann kommt der nächste Schritt.

von andre (Gast)


Lesenswert?

schlechten tag erwischt? sprich dich aus, das hilft dir vielleicht über 
deinen frust hinweg zu kommen...

von kljdsghökh (Gast)


Lesenswert?

Wie glaubst Du den Compiler zur Zusammenarbeit zu ueberreden, wenn Du 
Dich nicht an dessen Regeln haeltst? Eben, da kannst Du dessen 
Rechtschreibung beachten.

Aber bei uns hier denkst Du, die sollen mir doch bloss helfen, deren 
Regeln interessieren mich einen Sch.....dreck.

Dann interessieren uns Deine Probleme eben noch weniger.

Gast

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.