Problem beim Prozessauslesen

Alles rund um die Programmierung mit Qt
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Problem beim Prozessauslesen

Beitrag von slash-ex »

Ich muss einen Prozess auslesen, bzw. vielmehr die Ausgabe eines kleinen Programmes namens: "cat /proc/partitions".
Also wenn ich diese Fuktion mittels QStringList tmp = getPrcOutP("cat /proc/partitions"); aufrufe passiert anscheinend nichts?!

Das Programm durchläuft anscheinend diese Schleife nicht:

Code: Alles auswählen

	while(!txt_stream->atEnd() )
	{
		std::cout<<"read output: ";
		QString tmp_str = txt_stream->readLine();
		output.append(tmp_str);
		std::cout<<tmp_str.toStdString()<<std::endl;
	}
Was habe ich falsch gemacht? Eigentlich erwarte ich dass mir eine Ausgabe über meine Partitionen ausgegeben wird die so aussieht:

Code: Alles auswählen

major minor  #blocks  name

   3     0   78150744 hda
   3     1   35840983 hda1
   3     2          1 hda2
   3     5   20394486 hda5
   3     6   17832118 hda6
   3     7    3550333 hda7
   3     8     530113 hda8
Die Funktion:

Code: Alles auswählen

QStringList getPrcOutP(QString cmd)
{
	QProcess *process = new QProcess();
	std::cout<<"try to open: "<<cmd.toStdString()<<std::endl;
	process->start(cmd, QIODevice::ReadOnly);
	if (!process->waitForStarted() )
		std::cout<<"process couldn't get opened"<<std::endl;


	QTextStream *txt_stream = new QTextStream(process);

	QStringList output;
	while(!txt_stream->atEnd() )
	{
		std::cout<<"read output: ";
		QString tmp_str = txt_stream->readLine();
		output.append(tmp_str);
		std::cout<<tmp_str.toStdString()<<std::endl;
	}

	return output;

	process->close();
}
Könnte mir jemand verraten, wass ich beim Aulesen von Konsolenausgaben zu beachten habe?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Das return ist falsch da process nicht geschlossen wird, process wird nicht gelöscht und Du wartest nicht auf das Signal
QProcess::finished
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

An und für sich sollte es jetzt schon klappen! Aber irgendwie scheint der TextStream schon am Ende zus ein bevor er überhaupt anfängt! Ich weiß nicht wie man sonst noch die Konsolenausgabe abfängt!

Code: Alles auswählen

	while(!txt_stream->atEnd() )
	{
		std::cout<<"read output: ";
		QString tmp_str = txt_stream->readLine();
		output.append(tmp_str);
		std::cout<<tmp_str.toStdString()<<std::endl;
	}
Jetzt wird erst ein return geliefert, wenn der Prozess ein finished liefert.

Code: Alles auswählen

QStringList getPrcOutP(QString cmd)
{
	QProcess *process = new QProcess();
	std::cout<<"try to open: "<<cmd.toStdString()<<std::endl;
	process->start(cmd, QIODevice::ReadOnly);

	if (!process->waitForStarted() )
		std::cout<<"process couldn't get opened"<<std::endl;

	QTextStream *txt_stream = new QTextStream(process);

	QStringList output;
	while(!txt_stream->atEnd() )
	{
		std::cout<<"read output: ";
		QString tmp_str = txt_stream->readLine();
		output.append(tmp_str);
		std::cout<<tmp_str.toStdString()<<std::endl;
	}

	if(process->waitForFinished() )
	{
		process->close();
		std::cout<<"process finished: "<<std::endl;
		return output;
	}
}
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

hat denn keiner ne idee? es liegt nicht am return.. bis dahin hätte ich ein cout<< bekommen. un im moment ist das einzige ein "process finished"

also wird nichts was der porocess ausgibt gelesen. es liegt auf jedenfall nicht am befehl ("cat", etc), an den absoluten pfaden... an den argumenten und auch nicht an den membern:
waitForStarted()
==>waitForStarted(1) hilft auch nicht.

mal ne frage? habe ich nun einen fehler gemacht oder ist das ein bug im framework?

mir ist einer aufgefallen als ich eine von QWidget abgeleitete Klasse in ein QListwidget einfügen wollte... alles assistant konform...
slash-ex
Beiträge: 239
Registriert: 30. März 2005 21:40

Beitrag von slash-ex »

Code: Alles auswählen

QStringList getPrcOutP(QString cmd, QStringList args)
{
	QStringList output;
	QProcess *process = new QProcess();

	std::cout<<"try to open: "<<cmd.toStdString()<<std::endl;
	process->start(cmd, args/*, QIODevice::ReadOnly*/);

	if (!process->waitForStarted() )
		std::cout<<"process couldn't get opened"<<std::endl;

	// wait for finishing of the process
	process->waitForFinished();
	QTextStream *txt_stream = new QTextStream(process);

	while(!txt_stream->atEnd() )
	{
		std::cout<<"read output: ";
		QString tmp_str = txt_stream->readLine();
		output.append(tmp_str);
		std::cout<<tmp_str.toStdString()<<std::endl;

		if(txt_stream->atEnd() )
		{
			process->close();
			std::cout<<"process finished: "<<std::endl;
			return output;
		}
	}
}
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

Ist der letzte Post die komplett funktionierende Funktion?

Ich hab mich da ein wenig angelehnt, aber bei mir funktionierts leider nich.
Ich will die Ausgabe aber auch nicht auf der Konsole ausgeben, sondern in eine Datei umleiten. Das könnte ich bei "ping" auch mit ">>", aber ich will später die Zeilen überprüfen und nicht alle in die Datei ausgeben. Nämlich nur die tatsächlichen Antwortzeilen, nicht die Zusammenfassung etc.

Code: Alles auswählen

	QFile *ping_cmd = new QFile(ping_cmd_filename, this);
		
	ping_cmd->open(QIODevice::WriteOnly);
	ping_cmd->write(ping_cmd_str.toLatin1(), strlen(ping_cmd_str.toLatin1()));
	ping_cmd->close();
	
	ping->startDetached(ping_cmd_filename);
	
	QFile *ping_output_file =  new QFile("ping_output.log", this);
	ping_output_file->open(QIODevice::ReadWrite);
	
	ping->waitForFinished();
	QTextStream *ping_output = new QTextStream(ping);	
	
	while(!ping_output->atEnd())
	{
		QString tmp_string = ping_output->readLine();
		ping_output_file->write(tmp_string.toLatin1(), strlen(tmp_string.toLatin1()));
	}

	ping_output_file->close();
Also der Ping startet, schön in nem kleinen Konsolenfenster. Führt einen Ping durch und verschwindet wieder. Die ping_output.log wird auch erstellt, aber bleibt leider leer, 0Byte...

Sieht jemand meinen Fehler?

Und kann er mir bei der Gelegenheit gleich noch verraten, wie ich das Konsolenfenster verstecke? Also wie verhindere ich, dass das Fenster bei jedem Ping (es wird jede Sekunde/Minute/... einer durchgeführt) in der Vordergrund poppt?

Danke & Gruß
meph
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

Hat keiner ne Idee?

Ich hatte schon vermutet, dass es am OpenMode der Datei liegen könnte. Aber selbst wenn ich da Append nehm, kommt nix in der Datei an. Sie wird nichtmal angerührt, nachdem sie einmal erstellt wurde.

:evil:
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

1. Warum erzeugst du das komische Batch-File? Schau Dir mal die Doku zu QProcess an!
2. Wie versuchst Du von stdout/stderr zu lesen?? Hier hilft Dir auch die Doku weiter!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

1. Weil das auf Anhieb funktioniert hat und der Aufruf von QProcess mit Argumentenlisten nich. Da war ich zu faul mir das zurechtzufummeln.

2. readAllStandardOutput(); ?

Ich raff nich, wie ich das verwenden muss. Ich probier hier rum, aber et will nich ;-/

Wäre für nen weiteren Anstoss dankbar.

Danke!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

Hmmm :?:
main.cpp:160: error: 'class QProcess' has no member named 'addArgument'
main.cpp:161: error: 'class QProcess' has no member named 'addArgument'
main.cpp:162: error: 'class QProcess' has no member named 'addArgument'
Qt 4.1.4
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Manchmal kann man nur mit den Kopf schütteln... was spricht dagegen einfach mal die DOKU anzuschauen :roll:
http://doc.trolltech.com/4.1/qprocess#details
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

;)

Ich schüttel schon den ganzen Tag den Kopf über mich selbst. Und in der Doku rumgeschaut hab ich ja auch schon.

Wenn ich das richtig verstehe müsste ich doch mit meinem
ping->readAllStandardOutput() direkt und explizit auf die Standardausgabe meines Prozesses zugreifen, ohne irgendwelche ReadChannels für readLine() o.ä. zu setzen?! Wieso kann ich das denn dann nicht direkt in eine Datei schreiben?

Vielleicht sollte ichs für heute lassen. Ich reg mich nur über mich selbst auf :?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ich würde wie in der Doku beschrieben den Process erzeugen und dann das Signal readyReadStandardOutput () benutzen um die anliegenden Daten per readAllStandardOutput () auszulesen. Und das dann irgendwo speichern oder was auch immer damit machen.
QProcess ist zwar eine QIODevice, aber ich weiss atm nicht wie man das macht. Ich würde mal sagen man muss erst mit setReadChannelMode() & friends die gewünschten Channels festlegen. Aber bevor man da rumspielt ist readyReadStdout schneller ;-)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
mephistho
Beiträge: 58
Registriert: 14. September 2006 17:47

Beitrag von mephistho »

Ja, das seh ich genauso.

Dann poste ich mal ein wenig Code, der in meinen anfängerlichen Augen recht sinnvoll aussieht, aber leider nicht den gewünschten Effekt erzielt.

readFromStandardOutput() ist als public SLOT definiert.

Code: Alles auswählen

	ping->startDetached(ping_cmd_filename);
	
	connect(ping, SIGNAL(readyReadStandardOutput()), this, SLOT(readFromStandardOutput()));

Code: Alles auswählen

void MyWidget::readFromStandardOutput()
{
	QMessageBox::information(this, "Moep", "Test");

	QString ping_output_filename = QString("ping_output.log");
	QFile *ping_output_file =  new QFile(ping_output_filename, this);
	ping_output_file->open(QIODevice::Append);
	
	ping_output_file->write(ping->readAllStandardOutput());
	
	ping_output_file->close();
}
Mal abgesehen davon, wie schön/unschön das ist, müsste das doch funktionieren oder nich?

Aber er gibt z.B. nichtmal die MsgBox aus, wenn der Prozess gestartet und Daten ausgespuckt werden.

Danke für deine Geduld ;)
Antworten