Bekannt: dies scheint eine spezifische Frage Frage zu sein, aber hoffentlich kann es für alle im Zusammenhang mitLesen und Schreiben auf QProcess in Qt Console Application
Ich muss mit einem QProcess Objekt zu interagieren bearbeitet werden.
Das Problem:
ich von QProcess
nach dem Aufruf QProcess:write(input)
Mehr Infos bin keine Ausgabe bekommen:
Geht man durch die doc pages führte mich unter ein Beispiel zu erstellen:
Ich habe ein Skript, das Benutzereingaben anfordert und schließlich anzeigt und eine geeignete Nachricht basierend auf der Benutzereingabe.
Testing:
Nach dem Hinzufügen einer "log" -Funktion, um mein Skript für die Prüfung, geschieht Folgendes:
- Skript führt
- Skript Benutzereingabe anfordert (die ‚erste bestätigt '
qDebug() << p->readAll()
) - Skript akzeptiert Eingabe von
QProcess
(bestätigt durch Skript' Protokollausgabe ')
Danach wird keine Ausgabe empfangen. Die folgenden 2 debug Aussagen sowohl Feuer (d 30s warten jeweils)
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
Gefolgt von:
QString s = QString(p->readAll() + p->readAllStandardOutput());
wo s
eine leere Zeichenfolge ist.
Die Frage ist s
sollte entweder "Erfolg" oder "nicht bestanden"
Aufrufen von Code enthalten:
QString cmd = QString("sh -c \"/path/to/bashscript.sh\"");
QString input = QString("Name");
QString result = runCommand(cmd, input)
Prozess Code:
//takes 2 parameters,
// cmd which is the code to be executed by the shell
// input which acts as the user input
QString runCommand(QString cmd, QString input){
QProcess *p = new QProcess(new QObject());
p->setProcessChannelMode(QProcess::MergedChannels); //no actual reason to do this
p->start(cmd);
if (p->waitForStarted()) {
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
//reads current stdout, this will show the input request from the bash script
//e.g. please enter your name:
qDebug() << p->readAll();
//here I write the input (the name) to the process, which is received by the script
p->write(ps.toLatin1());
//the script should then display a message i.e. ("success" o "failed")
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
}
QString s = QString(p->readAll() + p->readAllStandardOutput());
return s;
}
else{
qDebug() << "waitForStarted() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
p->waitForFinished();
p->kill();
return QString();
}
script.sh (-rwxrwxr-x
)
#!/bin/bash
#returns
# "success" on non empty $n value
# "failed: on empty $n value
#
echo "enter your name:"
read n
if [[ ! -z $n ]];
then
echo "success"
exit 0;
else
echo "failed"
exit 1;
fi
UPDATE
@KevinKrammer ich den Startbefehl geändert, wie Sie gesagt hat, auch den QStringList mit dem args verwenden.
Immer noch nicht ausgegeben, tatsächlich die waitForReadyRead()
und waitForFinished()
returns false
sofort.
Called mit:
QString r = runCommand(QString("text"));
Prozess Code:
QString runCommand(QString input){
QProcess *p = new QProcess(new QObject());
p->setProcessChannelMode(QProcess::MergedChannels);
//script is the same script refered to earlier, and the `cd /home/dev` IS required
p->start("sh", QStringList() << "-c" << "cd /home/dev" << "./script");
;
if (p->waitForStarted()) {
if (!p->waitForReadyRead(5000)) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
qDebug() << p->readAll();
p->write(input.toLatin1());
if(!p->waitForFinished(5000)){
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
QString s = QString(p->readAll() + p->readAllStandardOutput());
return s;
}
else{
qDebug() << "waitForStarted() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
p->waitForFinished();
p->kill();
return QString();
}
Terminal-Ausgabe des Prozesses:
started
readChannelFinished
exit code = "0"
waitForReadyRead() [false] : CODE: "5" | ERROR STRING: "Unknown error"
""
waitForFinished() [false] : CODE: "5" | ERROR STRING: "Unknown error"
Press <RETURN> to close this window...
Gedanken dazu?
UPDATE 2
@Tarod Vielen Dank für die Zeit nehmen, um eine Lösung herzustellen.
Es funktioniert, wird jedoch nicht vollständig erwartet.
Ich kopierte über Ihren Code, genau.
ein paar Änderungen in der
Sehen Sie weitere Informationen unter mReadyReadStandardOutput()
gemacht.
Das Problem:
Nach dem Ausführen der Anwendung (und Skript), erhalte ich ein Ergebnis -> FANTASTISCHEN
Jedesmal, es ist das falsche Ergebnis heißt "nicht bestanden". -> NICHT FANTASTISCHEN
Terminal-Ausgang:
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"enter your name:\n"
""
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"failed\n"
Press <RETURN> to close this window...
Skriptinhalt:
#!/bin/bash
echo "enter your name:"
read n
echo $n > "/tmp/log_test.txt"
if [[ ! -z "$n" ]];
then
echo "success"
exit 0;
else
echo "failed"
exit 1;
fi
/tmp/log_test.txt
Ausgang
myname
diese läuft manuell von der Konsole:
[email protected]:~$ ls -la script
-rwxrwxr-x 1 dev dev 155 Jan 25 14:53 script*
[email protected]:~$ ./script
enter your name:
TEST_NAME
success
[email protected]:~$ cat /tmp/log_test.txt
TEST_NAME
Voll Code:
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
class MyProcess : public QProcess
{
Q_OBJECT
public:
MyProcess(QObject *parent = 0);
~MyProcess() {}
public slots:
void myReadyRead();
void myReadyReadStandardOutput();
};
MyProcess::MyProcess(QObject *parent)
{
connect(this,SIGNAL(readyRead()),
this,SLOT(myReadyRead()));
connect(this,SIGNAL(readyReadStandardOutput()),
this,SLOT(myReadyReadStandardOutput()));
}
void MyProcess::myReadyRead() {
qDebug() << Q_FUNC_INFO;
}
void MyProcess::myReadyReadStandardOutput() {
qDebug() << Q_FUNC_INFO;
// Note we need to add \n (it's like pressing enter key)
QString s = this->readAllStandardOutput();
qDebug() << s;
if (s.contains("enter your name")) {
this->write(QString("myname" + QString("\n")).toLatin1());
qDebug() << this->readAllStandardOutput();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyProcess *myProcess = new MyProcess();
QString program = "/home/dev/script";
myProcess->start("/bin/sh", QStringList() << program);
a.exec();
}
#include "main.moc"
Skript Ausgabe? QProcess-Problem?
warum Sie 'waitForFinished' fordern vor dem Schreiben? Gegeben Ihr Programm würde die Reihenfolge warten auf Start, dann Schleife auf Warten auf Lesen, bis Sie die erwartete Zeichenfolge erhalten haben, die schreiben, dann warten auf fertig. Für den Befehl würde ich auch empfehlen, Befehl und Argumente separat zu übergeben, d. H. Den Befehl als erstes Argument für 'start()' und alle seine Parameter als zweiten, da dies auch korrekt und automatisch spacing behandelt. –
@KevinKrammer Vielen Dank für den Vorschlag, ich werde es anwenden und mit einem Ergebnis – KGCybeX
@KevinKrammer zurückkehren, die ein Nein ist. Bitte sehen Sie update – KGCybeX