在Qt控制台应用程序中读取和写入QProcess
注意:这似乎是一个具体的问题,但希望它可以编辑为所有相关
我需要与QProcess对象进行交互。
问题:
  在调用QProcess:write(input)之后,我没有从QProcess获得任何输出QProcess:write(input) 
更多信息:
阅读文档页面让我在下面创建一个示例:
我有一个请求用户输入的脚本,最后根据用户输入显示和适当的消息。
测试:
将“日志”功能添加到我的脚本进行测试后,会发生以下情况:
qDebug() << p->readAll() ) QProcess输入(由脚本'日志输出'确认) 在此之后,没有收到任何输出。 以下两条调试语句都会触发(即每个都等待30秒)
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());
  其中s是一个空字符串。 
  问题是s应包含“成功”或“失败” 
调用代码:
QString cmd = QString("sh -c "/path/to/bashscript.sh"");
QString input = QString("Name");
QString result = runCommand(cmd, input)
流程代码:
//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我修改了运行命令,就像你说的,同样使用QStringList和args。
  仍然没有得到输出,事实上waitForReadyRead()和waitForFinished()立即returns false 。 
呼叫:
QString r = runCommand(QString("text"));
流程代码:
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();
}
流程的终端输出:
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...
对此有何想法?
更新2
@塔罗德感谢您花时间制定解决方案。
它工作,但不完全是预期的。
我完全抄袭了你的代码。
  在mReadyReadStandardOutput()做了一些更改 
请参阅以下其他信息。
问题:
运行应用程序(和脚本)后,我得到一个结果 - >真棒
每次它是不正确的结果,即“失败”。 - >不是真的
终端输出:
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"enter your name:n"
""
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"failedn"
Press <RETURN> to close this window...
脚本内容:
#!/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输出 
myname
从控制台手动运行此操作:
dev@dev-W55xEU:~$ ls -la script 
-rwxrwxr-x 1 dev dev 155 Jan 25 14:53 script*
dev@dev-W55xEU:~$ ./script 
enter your name:
TEST_NAME
success
dev@dev-W55xEU:~$ cat /tmp/log_test.txt 
TEST_NAME
完整代码:
#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"
脚本问题? QProcess问题?
不幸的是我没有你所有的代码,所以我举了一个例子。 我希望它能帮助你。
  如果我将自己的代码与您的代码进行比较,我认为问题可能在于您没有在写入之后调用readAllStandardOutput() ,也可能没有在main.cpp中调用exec() 。 
#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)
    this->write(QString("myname" + QString("n")).toLatin1());
    // Next line no required
    // qDebug() << this->readAll();
    qDebug() << this->readAllStandardOutput();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyProcess *myProcess = new MyProcess();
    QString program = "/home/fran/code/myscript.sh";
    myProcess->start("/bin/sh", QStringList() << program);
    a.exec();
}
#include "main.moc"
测试应用程序的脚本:
echo "enter your name:"
read n
if [ ! -z "$n" ];
then
    echo "success"
    exit 0;
else
    echo "failed"
    exit 1;
fi
上一篇: reading and writing to QProcess in Qt Console Application
