Seite 1 von 1

System Befehle im Hintergrund starten und in label umleiten

Verfasst: 12. Juli 2011 20:00
von js
Schönen guten Abend.

Ich arbeite mit dem Visual Studio 2005 und Qt+ Qt Designer und möchte dass über ein Thread eine externe Konsole ( im Hintergrund ) gestartet wird.
Das passiert auch soweit ganz gut, jedoch soll der Inhalt ständig in einem Label ausgegeben werden.
Gibt es dafür eine Möglichkeit außer das ganze in eine text Datei umzuleiten und diese ständig auszulesen ?
lg.

Der Code:
thread.cpp

Code: Alles auswählen

#include "thread.h"
#include "openneu.h"


Thread::Thread() {
	
}

void Thread::run() {
	//Hier findet die eigentliche Arbeit statt 
	system("cmd");
} 
thread.h

Code: Alles auswählen

//thread.h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include "ui_openneu.h"

class Thread : public QThread  {
   Q_OBJECT
	   
public:
	Thread();
protected:
   void run();	   
};

#endif
openneu.cpp

Code: Alles auswählen

#include <QtGui>
#include "openneu.h"
#include "thread.h"

openneu::openneu(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
    ui.setupUi(this);

    connect( ui.pushButton, SIGNAL( clicked() ),this , SLOT( eigenfunktion() ) );
	connect( ui.pushButton_2, SIGNAL( clicked() ),this , SLOT( startThread1() ) );
}

openneu::~openneu()
{

}

void openneu::threadlauft() {
        ui.label->setText("Thread läuft schon");
    }

void openneu::threadReady() {
        ui.label->setText("Thread ist fertig");
    }

void openneu::startThread1()
{
        if(thread1.isRunning()) {
        threadlauft();
        connect(&thread1, SIGNAL(finished()),
            this, SLOT( threadReady())); }

        else {  
            thread1.start(); }
	 // thread1.start();
} 
openneu.h

Code: Alles auswählen

#ifndef OPENNEU_H
#define OPENNEU_H

#include <QtGui/QMainWindow>
#include "ui_openneu.h"
#include "thread.h"

class openneu:  public QMainWindow 
{
    Q_OBJECT

public:
    openneu(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~openneu();

private:
	Thread thread1;
    Ui::openneuClass ui;
public slots:
	void threadlauft();
    void threadReady();
    void startThread1(); 

        void eigenfunktion()
        {
        ui.label->setText("test");
        }


};


#endif // OPENNEU_H
main.cpp

Code: Alles auswählen

#include <QtGui/QApplication>
#include "openneu.h"


int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	openneu w;
	w.show();
	return a.exec();
}

Verfasst: 12. Juli 2011 20:04
von Christian81
Qt Doku -> QProcess

Verfasst: 12. Juli 2011 20:07
von franzf
Jippie :D Einen Thread nehmen um system zu starten :D
system alleine sollte schon "starten und vergessen", da blockiert nix, ein Thread ist unnötig wie ein Wahlversprechen.

Und der "Inhalt der Konsole" ist doch sicher der Output der Applikation die darin gestartet wird, oder?

Lösung:
Beschäftige dich mit QProcess, speziell wie man bestimmte channels (stdout, stderr, ...) lesen kann - steht in der Doku zu QProcess.

Verfasst: 12. Juli 2011 21:04
von js
@franzf

mit dem system() soll eine externe Funktion gestartet werden welche komplizierte Berechnungen durchführt. Wollte mit dem Thread dafür sorgen das, dass Hauptprogramm dabei noch reagieren kann.
lg

Verfasst: 12. Juli 2011 22:23
von Christian81
Nochmal: Lies die Doku zu QProcess !

Verfasst: 12. Juli 2011 22:58
von js
Habe versucht es umzusetzen. Leider passiert nichts wenn ich auf Button_2 drücke...

openneu.h

Code: Alles auswählen

#ifndef OPENNEU_H
#define OPENNEU_H

#include <QtGui/QMainWindow>
#include <QProcess>
#include "ui_openneu.h"
#include "thread.h"

class openneu:  public QMainWindow 
{
    Q_OBJECT

public:
    openneu(QWidget *parent = 0, Qt::WFlags flags = 0);
	QProcess *asynchron;
    ~openneu();

private:
	Thread thread1;
    Ui::openneuClass ui;
public slots:
//Für QProcess
	void asynchronProcess();
	void readproc();

//Für Threads
    void threadlauft();
    void threadReady();
    void startThread1(); 
    void eigenfunktion()
    {
      ui.label->setText("test");
    }
};

#endif // OPENNEU_H
openneu.cpp

Code: Alles auswählen

#include <QtGui>
#include "openneu.h"
#include "thread.h"
#include <QProcess>
#include <QInputDialog>

openneu::openneu(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
asynchron = new QProcess();
connect(asynchron, SIGNAL(readproc()), this, SLOT(readproc()));

    ui.setupUi(this);
    connect( ui.pushButton, SIGNAL( clicked() ),this , SLOT( eigenfunktion() ) );
connect( ui.pushButton_2, SIGNAL( clicked() ),this , SLOT( asynchronProcess() ) );
}

openneu::~openneu()
{

}

void openneu::threadlauft() {
        ui.label->setText("Thread läuft schon");
    }

void openneu::threadReady() {
        ui.label->setText("Thread ist fertig");
    }

void openneu::startThread1()
{
        if(thread1.isRunning()) {
        threadlauft();
        connect(&thread1, SIGNAL(finished()),
            this, SLOT( threadReady())); }

        else {  
            thread1.start(); }

} 

//Einen asynchronen Prozess starten
void openneu::asynchronProcess(){
	asynchron->start("cmd");
}

//Zeilenweise vom asynchronen Prozess lesen
void openneu::readproc(){
	QByteArray line;
	if( asynchron->state() != QProcess::Running ){
		ui.textEdit->setText("Prozess läuft nicht!");
		return;
	}
	while(! (line =asynchron->readLine()). isEmpty() ) {
		ui.textEdit->moveCursor( QTextCursor::End );
		QString output(QString::fromLatin1(line));
		output.chop(2);
		ui.textEdit->insertPlainText(output);
	}
}

Verfasst: 12. Juli 2011 23:36
von solarix
1.

Code: Alles auswählen

asynchron = new QProcess();
connect(asynchron, SIGNAL(readproc()), this, SLOT(readproc())); 
Wo genau hast du in der Doku gelesen, dass "QProcess" ein Signal "readproc()" hat?

2.

Code: Alles auswählen

void openneu::asynchronProcess(){
   asynchron->start("cmd");
} 
Was wenn "cmd" nicht startet..? Ich würde da allenfalls prüfen, ob der Start gut verläuft..

3.
Was wenn "cmd" nichts ausgibt? Evt. sollte man noch auf das Ende-Signal von QProcess reagieren..

4.
Public-Variabeln sind eigentlich immer schlecht :wink:

hth..

[EDIT]
5. deine QProcess-Instanz wird nirgendwo zerstört...

Verfasst: 13. Juli 2011 01:46
von js
@solarix
Du Genie, habe es nicht gesehen es muss natürlich
connect(asynchron, SIGNAL(readyRead()), this, SLOT(readproc()));
heißen.
Und schwups die cmd wird in dem Texteditor ausgegeben.
Die Fehlermeldungen sind realesiert jedoch habe ich noch Probleme die pid , exitStatus und terminate zu erstellen

Code: Alles auswählen

#include <QtGui>
#include "openneu.h"
#include "thread.h"
#include <QProcess>
#include <QInputDialog>
#include <QMessageBox>

openneu::openneu(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)
{
asynchron = new QProcess();
connect(asynchron, SIGNAL(readyRead()), this, SLOT(readproc()));

    ui.setupUi(this);
    connect( ui.pushButton, SIGNAL( clicked() ),this , SLOT( eigenfunktion() ) );
	//connect( ui.pushButton_2, SIGNAL( clicked() ),this , SLOT( startThread1() ) );
	connect( ui.pushButton_2, SIGNAL( clicked() ),this , SLOT( asynchronProcess() ) );
	connect( asynchron, SIGNAL( error(QProcess::ProcessError) ),this , SLOT( processError(QProcess::ProcessError) ) );
	connect( ui.pushButton_3, SIGNAL( clicked() ),this , SLOT( asynchron->terminate() ) );
}

openneu::~openneu()
{

}

void openneu::threadlauft() {
        ui.label->setText("Thread läuft schon");
    }

void openneu::threadReady() {
        ui.label->setText("Thread ist fertig");
    }

void openneu::startThread1()
{
        if(thread1.isRunning()) {
        threadlauft();
        connect(&thread1, SIGNAL(finished()),
            this, SLOT( threadReady())); }

        else {  
            thread1.start(); }

} 

//Einen asynchronen Prozess starten
void openneu::asynchronProcess(){

    /* QString program = "cmd.exe";
     QStringList arguments;
     arguments << "dir";
     asynchron->start(program, arguments); */
	//if( asynchron->state() != QProcess::Running ){ui.textEdit->setText("Prozess läuft nicht!");}

QString str;
str.append(asynchron->exitStatus());

asynchron->start("cmd");
if( asynchron->state() == QProcess::Running ){	 
ui.textEdit->setText(str);
Q_PID tmpPid =  asynchron->pid();}
     //ui.textEdit->setText(tmpPid);

}


//Zeilenweise vom asynchronen Prozess lesen
void openneu::readproc(){
	QByteArray line;
	if( asynchron->state() != QProcess::Running ){
		ui.textEdit->setText("Prozess läuft nicht!");
		return;
	}
	while(! (line =asynchron->readLine()). isEmpty() ) {
		ui.textEdit->moveCursor( QTextCursor::End );
		QString output(QString::fromLatin1(line));
		output.chop(2);
		ui.textEdit->insertPlainText(output);
	}
}

// Fehler bei einem asynchronen Prozess auswerten
void openneu::processError(QProcess::ProcessError e) {
	QString err("Der Prozess konnte nicht gestartet werden\n");
		err.append("Folgender Fehler ist aufgetreten: ");
	switch( e ) {
		case QProcess::FailedToStart:
			err.append("Failed to Start\n");
			break;
		case QProcess::Crashed:
			err.append("Crashed\n");
			break;
		case QProcess::Timedout:
			err.append("Timeout\n");
			break;
		case QProcess::WriteError:
			err.append("WriteError\n");
			break;
		case QProcess::ReadError:
			err.append("ReadError\n");
			break;
		case QProcess::UnknownError:
			err.append("UnknownError\n");
			break;
	}
	ui.textEdit->setText(err);
}


Verfasst: 13. Juli 2011 06:33
von Christian81
connect( ui.pushButton_3, SIGNAL( clicked() ),this , SLOT( asynchron->terminate() ) );
Bitte lies die Doku zu Signals und Slots, überprüfe den Rückgabewert von connect() und außerdem schau was dein Programm zur Laufzeit auf der Konsole ausgibt. Das wirst du an drei verschiedenen Stellen sehen dass dies nicht funktioniert...

Verfasst: 14. Juli 2011 18:42
von js
Alles klar. Läuft.
//openneu.cpp

Code: Alles auswählen

connect( ui.pushButton_3, SIGNAL( clicked() ),this , SLOT( asystop() ) );
void openneu::asystop() {
asynchron->kill(asynchron->pid(), SIGSTOP);
// asynchron->kill(asynchron->pid(), SIGCONT);
}
//openneu.h

Code: Alles auswählen

…
public slots:
	void asystop();
…
1) Jedoch nur wenn ich kill() benutze, mit terminate() passiert nichts. Habe mir auch gedachte vielleicht könnte man die externen Prozess auch pausieren. Leider kommt die Fehlermeldung: Das SIGSTOP nicht gefunden wurde, trotz #include <signal.h>

2) Würde gerne die PID ausgeben, kann aber über label nur QString ausgeben und bekomme die Umwandlung nicht hin.


//PID anzeigen

Code: Alles auswählen

QString pid=int(asynchron->pid());
pid.toAscii().data();
ui.label->setText(pid);

3) Im text editor wird neben dem Inhalt der cmd.exe noch : Das System hat keinen Meldungstext f

Verfasst: 14. Juli 2011 18:48
von Christian81
2) Würde gerne die PID ausgeben, kann aber über label nur QString ausgeben und bekomme die Umwandlung nicht hin.
Doku zu QString lesen schadet nicht ...

Verfasst: 14. Juli 2011 21:15
von js

Code: Alles auswählen

//PID anzeigen
Q_PID pid=asynchron->pid();
QString par;
ui.label->setText(par.number(pid));
Konvertierung des Parameters 1 von 'Q_PID' in 'int' nicht möglich.
Habe keine Idee mehr

Hast du auch eine Idee wegen, 1 und 3
lg js