Probleme mit QProcess

Du bist neu in der Welt von C++? Dann schau hier herein!
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Probleme mit QProcess

Beitrag von TerraG »

Hallo,

möchte gerne wissen warum folgendes nicht funktioniert:

Habe in meiner Klasse ein Zeigerobjekt ErstelleMaße von QProcess angelegt mit

Code: Alles auswählen

QProcess *ErstelleMaße;
Nun will ich am Ende einer Methode (ist mit einem Button connected), die zur Erstellung eines Ordners mit Unterordners dient das Arbeitsverzeichnis für ErzeugeMaße festlegen mit

Code: Alles auswählen

ErstelleOrdner()
{
Anweisung zur Erstellung der Ordner mit QFileDialog...

QProcess *ErstelleMaße = new QProcess(this);
ErstelleMaße->setWorkingDirectory (erstellterHauptordner);
}
Frage hier: Setze ich damit das Arbeitsverzeichnis von Erstelle Maße auf den QString erstellterHauptordner?

Letztlich will ich natürlich den Prozess in einer weiteren Methode Maßerzeugung (wiederum mit einem Button connected) ausführen:

Code: Alles auswählen

    QString ErzeugeMaßeBefehlspfad = "./PfadzumProg";

    QProcess *ErzeugeMaße = new QProcess(this);
    ErzeugeMaße->start(ErzeugeMaßeBefehlspfad);
    ErzeugeMaße->exitStatus ();
Hier hab ich jetzt das Problem, dass einfach nichts passiert, d.h. exitStatus gibt mir keine Meldung (0 oder 1) und es sollten mit dem Programm (binaryDatei) bestimmte Dateien erstellt werden, was auch nicht passiert. Kann mir jemand einen Tipp geben, hänge schon ewig daran fest?
Gruß
TerraG
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Probleme mit QProcess

Beitrag von brax »

1. Die Doku zu QProcess::start gibt Dir vielleicht schon einen ganz guten Tipp
Note: Processes are started asynchronously, which means the started() and error() signals may be delayed. Call waitForStarted() to make sure the process has started (or has failed to start) and those signals have been emitted.
Nun guck Dir Deinen Code an und die Stelle an der Du den exitStatus abfragst. Ist dort der Prozess sicher schon beendet?

2. Ja, Du setzt mit Deinem Aufruf von setWorkingDirectory das Arbeitsverzeichnis des in der Zeile vorher erzeugten QProcess Objektes. Nun meine Frage: meinst Du wirklich, das es sich bei dem QProcess Objekt um dasselbe handelt, wie das auf dem Du im zweiten Codeschnipsel "start" aufrufst? Du weißt schon Gültigkeitsbereich von Variablen und so.... (im Moment erzeugst Du in ErstelleOrdner() einfach nur ein tolles Speicherloch). Du hast doch anfangs gesagt, Du hast Dir die Variable schon als Member inder Klasse angelegt, warum definierst Du immer neue davon? Erzeugen brauchst Du den QProcess dann natürlich auch nur einmal.
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Danke ersteinmal für die Antwort.

Zu1. Habe jetzt vor die Methode "exitStatus();" die Methode "waitForStarted();" gesetzt.

Zu2. Ich hatte es zuerst so probiert, dass ich in der Klasse ein public Member als

Code: Alles auswählen

QProcess *ErstelleMaße;
deklariert hatte.

Nun wollte ich diesen Member in der Methode zur Ordnererstellung wie folgt nutzen:

Code: Alles auswählen

ErstelleOrdner()
{
Anweisung zur Erstellung der Ordner mit QFileDialog...

ErstelleMaße->setWorkingDirectory (erstellterHauptordner);
}
Wenn ich aber jetzt auf den pushButton klicke der diese Methode ausführt und dann einen Ordner anlege und öffne, wird die GUI geschlossen und ich bekomme die Fehlermeldung "Das Programm ist abgestürzt".

Ich gehe mal davon aus, dass ich mit dem anderen Versuch

Code: Alles auswählen

QProcess *ErstelleMaße = new QProcess(this);
jedes mal ein neues Zeigerobjekt in den Methoden angelegt hatte (ein lokales Objekt), unabhängig davon ob ich ein solches mit gleichem Namen in der Klasse deklariert hatte?
Gruß
TerraG
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit QProcess

Beitrag von franzf »

1) ErstelleMaße ist kein gültiger Name. Ein Zeichen ist dabei, welches nicht gestattet ist.
2) QProcess *ErstelleMaße; ist ne Deklaration eines Pointers auf einen QProcess. Damit sagst du automatisch "Ich kümmere micht selber um Erstellung und Zerstörung". Deshalb erzeugt der Compiler auch noch kein Objekt, das machst du mit dem ersten new. Das new weglasse erzeugt undefiniertes Verhalten. Allerdings ist dein anderer Weg (neuen Pointer deklarieren) auch keine Lösung - dein Klassenmember ist weiterhin uninitialisiert
Du willst eigentlich den Member initialisieren. Das sind tiesfste C++-Grundlagen.
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Und wie sieht es damit aus:

Deklaration in der Klasse:

Code: Alles auswählen

QProcess ErstelleMase;
Methode zur Ordnererstellung:

Code: Alles auswählen

ErstelleOrdner()
{
Anweisung zur Erstellung der Ordner mit QFileDialog...

ErstelleMase.setWorkingDirectory (erstellterHauptordner);
}
Methode für Prozess:

Code: Alles auswählen

QString ErstelleMaseBefehlspfad = "./PfadzumProg";
ErstelleMase.start(ErstelleMaßeBefehlspfad);
ErstelleMase.waitForFinished;    
ErstelleMase.exitStatus ();
Hab das ganze also jetzt mit einem normalen Objekt und keinem Zeigerobjekt gemacht. Bringt das Nachteile?
Des weiteren kriege ich immer noch keine Ausgabe wenn ich den Prozess starte, d.h. es werden keine Ordner erstellt und "exitStatus()" gibt mir auch keine Rückmeldung.
Zuletzt geändert von TerraG am 28. Januar 2012 13:18, insgesamt 1-mal geändert.
Gruß
TerraG
Herzogswalder
Beiträge: 79
Registriert: 11. Oktober 2009 00:37
Wohnort: Dresden

Re: Probleme mit QProcess

Beitrag von Herzogswalder »

Was erwartest du denn für eine Ausgabe, wenn du nur

Code: Alles auswählen

ErzeugeMaße->exitStatus ();
da zu stehen hast?

Dokumentation -> QProcess::ExitStatus QProcess::exitStatus() const
Gruß, Herzogswalder
Qt 4.8, OS X Mountain Lion
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Hi,

hab jetzt damit die Ausgabe bekommen:

Code: Alles auswählen

 ErstelleMase.start(ErstelleMaseBefehlspfad);
   ErstelleMase.waitForFinished();
    ErstelleMase.exitStatus();
    bool result = ErstelleMase.exitStatus();
    std::cout << result << std::endl;
Was bedeutet es denn wenn in der Beschreibung einer Methode z.B. steht:
Returns the exit status of the last process that finished.
?
Was heisst das jetzt für mich?
Gruß
TerraG
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Probleme mit QProcess

Beitrag von franzf »

Dass wenn dein Prozess zu Ende ist, du einen aussagekräftigen Wert daraus bekommst. Vorher aufrufen macht keinen Sinn. Wenn du das QProcess-Objekt benutzt, um nocht weitere Prozesse zu starten, kommst du an den ersten exitStatus nicht mehr ran, wenn schon der zweite Prozess gestartet wurde.
Warum rufst du jetzt eigentlich 2x exitStatus auf? Und warum verwendest du keine Instanz des enums QProcess::ExitStatus, sondern castest nach bool? (Letzteres ist nicht so megatragisch, weil ExitStatus nur 0 und 1 kennt, eine schlechte ANgewohnheit ist es trotzdem - und gewonnen hast du damit gar nichts).
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Hi,

ich schau mir das mit dem enum Datentyp mal an, außerdem auch noch Zeiger auf Member einer Klasse und Zeiger auf Funktionen. Das mit dem Doppelaufruf war ein Versehen.

Ich werd dann mit dem Tutorium http://www.cpp-tutor.de/cpp/hinweise.html nochmal arbeiten.

Ciao
Gruß
TerraG
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Hab das jetzt mal wie folgt gemacht:

Code: Alles auswählen

QString ErstelleMaseBefehlspfad = "./Pfad zur binaryDatei"; 

    Prozess.start(ErstelleMaseBefehlspfad);  
    Prozess.waitForFinished();                 
    QProcess::ExitStatus Status = Prozess.exitStatus();

    if (Status == 0)
    {
      std::cout << "Die Anwendung wurde normal durchgeführt!" << std::endl;
      ui.pushButtonSimstarten -> setEnabled(true);
    }
    if (Status == 1)
    {
        std::cout << "Die Anwendung wurde nicht ausgeführt.Es kam zu einem Fehler!" << std::endl;
    }
Compiliert auch ohne Probleme und exitStatus() gibt auch 0 aus. Das Problem ist nur, dass die Anwendung nicht stattfindet. U.a. merke ich das daran, dass direkt nach Aktivierung der Methode durch den Button die Meldung "Die Anwendung wurde normal durchgeführt!" ausgegeben wird, obwohl die Anwendung dann noch garnicht beendet sein kann (wenn sie durchgelaufen wäre xD), da sie zumindest ein paar Sekunden braucht. Außerdem werden auch nicht die Dateien, welche die Anwendung erstellen sollte abgelegt.

Ist denn mit dem Quelltext alles in Ordnung? und geht es auch in Ordnung, dass ich bereits in der ErstelleOrdner Methode die WorkingDirectory für den Prozess festgelegt habe (siehe folgendes)?

Code: Alles auswählen

ErstelleOrdner()
{
Anweisung zur Erstellung der Ordner mit QFileDialog...

Prozess.setWorkingDirectory (erstellterHauptordner);
}
Im Terminal läuft die Anwendung normalerweise so ab, dass man in das Verzeichnis (Ordner) in dem bestimmte Dateien liegen wechselt und dann einfach den Befehl "blockMesh" aufruf. Die Anwednung erzeugt dann in einem Unterordner des gewählten Verzeichnisses neue Dateien.
Ich hoffe doch, dass ich mit der Kombination aus Prozess.setWorkingDirectory() und Prozess.start() "analog zum Vorgang im Terminal vorgegangen bin"?
Gruß
TerraG
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Probleme mit QProcess

Beitrag von Christian81 »

Gibt der Prozess was auf die Kommandozeile aus? Wenn ja -> dies ausgeben (siehe Doku).
Muss der Prozess in einem bestimmten Verzeichnis ausgeführt werden? Wenn ja -> Arbeitsverzeichnis setzen (wieder siehe Doku)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Probleme mit QProcess

Beitrag von brax »

1. Ist es wahrscheinlich wirklich hilfreich, wenn Du die Ausgabe des QProcess abfängst und diese Dir ausgibst.

2. Schau Dir mal das Beispiel in der Doku nochmal an. Ich bin mir nicht 100% sicher, ob es so, wie Du es machst, funktionieren kann. Hier mal das Beispiel aus der Doku:

Code: Alles auswählen

     QProcess gzip;
     gzip.start("gzip", QStringList() << "-c");
     if (!gzip.waitForStarted())
         return false;

     gzip.write("Qt rocks!");
     gzip.closeWriteChannel();

     if (!gzip.waitForFinished())
         return false;

     QByteArray result = gzip.readAll();
Und fällt Dir was auf? (Tipp: Zeile 3!)

3. (aber das ist gerade nicht wirklich Dein Problem) bei einem Rückgabewert == 1 zu sagen, dass das Programm nicht ausgeführt würde ist auch nicht so ganz korrekt, oder? Der Rückgabewert kommt ja vom AUSGEFÜHRTEN Programm! Und... meldet Dein Programm einen Fehler wirklich nur mit 1? Kann es nicht auch z.B. 255 oder so sein?
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Wie kann ich denn ein QByteArray ausgeben? xD Um die Ausgabe des Prozesses abzufangen und zu speichern, habe ich

Code: Alles auswählen

 QByteArray LOW = Prozess.readAllStandardOutput ();
eingefügt. Richtig?

Wie kann ich mir das aber jetzt ausgeben lassen?, weil mit std::cout geht es nicht. Bei der QBiteArray Class seh ich nicht welchen Befehl ich zur Ausgabe nutzen kann.
Gruß
TerraG
TerraG
Beiträge: 81
Registriert: 13. Oktober 2011 15:23

Re: Probleme mit QProcess

Beitrag von TerraG »

Ok,

habs jetzt wie folgt gemacht:

Code: Alles auswählen

QString ErstelleMase ="Pfad zur binary"
Prozess.start(ErstelleMase);
Prozess.waitForFinished();                 // Warte bis der Prozess (Anwendung) beendet wurde
QProcess::ExitStatus Status = Prozess.exitStatus();

QByteArray LOW = Prozess.readAllStandardOutput (); // Ausgabe der Anwednung prüfen 
    char *data = LOW.data();
    std::cout<<*data;

if (Status == 0)
    {
      std::cout << "Die Anwendung wurde normal durchgeführt!" << std::endl;
      ui.label3SimStarten -> setEnabled(true);
      ui.comboBoxSimSolver -> setEnabled(true);
      ui.pushButtonSimstarten -> setEnabled(true);
    }
    if (Status == 1)
    {
        std::cout << "Die Anwendung Gittererstellung (blockMesh) wurde nicht ausgeführt.Es kam zu einem Fehler!" << std::endl;
    }
Die Ausgabe die mir jetzt "readAllStandardOutput ()" geliefert hat, ist ein kleines Rechteck. Nicht mehr und nicht weniger LOL. Kein Plan woran das liegt, werde wohl morgen beim Lehrstuhl vorbei schauen, um zu versuchen das zu klären.
Gruß
TerraG
brax
Beiträge: 208
Registriert: 11. Mai 2010 11:22

Re: Probleme mit QProcess

Beitrag von brax »

Hat Du Dir meine letzte Antwort wirklich durchgelesen? Versuch es mal nochmal.... (Nochmal der Tipp: Zeile 3 von dem Beispiel, dass ich gepostet habe, ein Prozess kann nicht beendet sein, bevor er gestartet wurde).

Ein QByteArray lässt sich ganz einfach in einen QString umwandeln. Vergiß std::cout und benutze Qt! qDebug und co. sind Dein Freund!
Antworten