本文介绍了在Qt Console应用程序中读写QProcess的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这似乎是一个特定的问题,但希望可以对其进行所有与之相关的编辑



我需要进行互动



问题:



我什么也没得到 QProcess 在调用 QProcess之后的输出:write(input)



更多信息:



通过导致我在下面创建了一个示例:



我有一个脚本,要求用户输入并最终显示



测试:



添加后我的脚本的日志功能进行测试,会发生以下情况:




  • 脚本执行

  • 脚本请求用户输入(由'first' qDebug()<< p-> readAll()确认)

  • 剧本接受来自 QProcess 的输入(由脚本 log output确认)



之后这,没有收到输出。以下两个调试语句均会触发(即等待30秒)

  if(!p-> waitForReadyRead()){
qDebug()<< waitForReadyRead()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
if(!p-> waitForFinished()){
qDebug()<< waitForFinished()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}

接着:

  QString s = QString(p-> readAll()+ p-> readAllStandardOutput()); 

其中 s 是一个空字符串。 / p>

问题是 s 包含成功或失败

呼叫代码:

  QString cmd = QString( sh -c \ /path/to/bashscript.sh\); 
QString输入= QString(名称);
QString结果= runCommand(cmd,输入)

过程代码:

  //接受2个参数,
// cmd,这是外壳程序要执行的代码
//作为用户输入的输入

QString runCommand(QString cmd,QString input){
QProcess * p = new QProcess(new QObject());
p-> setProcessChannelMode(QProcess :: MergedChannels); //没有实际理由这样做
p-> start(cmd);
if(p-> waitForStarted()){
if(!p-> waitForReadyRead()){
qDebug()<< waitForReadyRead()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
if(!p-> waitForFinished()){

//读取当前标准输出,这将显示来自bash脚本
的输入请求/例如请输入您的姓名:
qDebug()<< p-> readAll();

//在这里,我将输入(名称)写入进程,由脚本
p-> write(ps.toLatin1())接收。

//脚本随后应显示一条消息,即( success o failed)
if(!p-> waitForReadyRead()){
qDebug() << waitForReadyRead()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
if(!p-> waitForFinished()){
qDebug()<< waitForFinished()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
}
QString s = QString(p-> readAll()+ p-> readAllStandardOutput());
return s;
}
else {
qDebug()<< waitForStarted()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
p-> waitForFinished();
p-> kill();
return QString();
}

script.sh -rwxrwxr-x

 #!/ bin / bash 
#返回
#成功在非空$ n值
#失败:在空$ n值

echo输入您的名字:
读n
if [[!!z $ n]];
然后
echo success
exit 0;
else
echo failed
出口1;
fi

更新



@KevinKrammer我也按照您所说的那样修改了运行命令,还使用了带有args的QStringList。



仍然没有得到输出,实际上 waitForReadyRead() waitForFinished() 返回false



调用如下:

  QString r = runCommand(QString (文字)); 

处理代码:

  QString runCommand(QString输入){

QProcess * p =新的QProcess(new QObject());
p-> setProcessChannelMode(QProcess :: MergedChannels);

//脚本与前面提到的脚本相同,并且需要使用cd / home / dev`
p-> start( sh,QStringList()<< ; -c<< cd / home / dev<< ./script);
;
if(p-> waitForStarted()){
if(!p-> waitForReadyRead(5000)){
qDebug()<< waitForReadyRead()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
qDebug()<< p-> readAll();
p-> write(input.toLatin1());
if(!p-> waitForFinished(5000)){
qDebug()<< waitForFinished()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
QString s = QString(p-> readAll()+ p-> readAllStandardOutput());
return s;
}
else {
qDebug()<< waitForStarted()[false]:代码:<< QVariant(p-> error())。toString()<< |错误字符串:<< p-> errorString();
}
p-> waitForFinished();
p-> kill();
return QString();
}

过程的最终输出:

 已开始
readChannelFinished
退出代码= 0
waitForReadyRead()[false]:代码: 5 |错误字符串:未知错误

waitForFinished()[false]:代码: 5 |错误字符串:未知错误
按< RETURN>关闭此窗口...

对此有何看法?



更新2



@Tarod感谢您抽出宝贵时间提出解决方案。



它可以工作,但是不能完全预期。



我完全复制了您的代码。



mReadyReadStandardOutput()



进行了一些更改。



问题:



运行应用程序(和脚本)后,我得到一个结果- >很棒



每次都是不正确的结果,即失败。 ->很棒



终端输出:

  void MyProcess :: myReadyRead()
void MyProcess :: myReadyReadStandardOutput()
输入您的名称:\n

void MyProcess :: myReadyRead( )
void MyProcess :: myReadyReadStandardOutput()
failed\n
按< RETURN>关闭此窗口...

脚本内容:

 #!/ bin / bash 
echo输入您的名字:
读n
echo $ n > /tmp/log_test.txt
如果[[! -z $ n]];
然后
echo success
exit 0;
else
echo failed
exit 1;
fi

/tmp/log_test.txt 输出

 我的名字

从控制台手动运行此操作:

  dev @ dev-W55xEU:〜$ ls -la脚本
-rwxrwxr-x 1 dev dev 155 Jan 25 14:53脚本*

dev @ dev-W55xEU:〜$。 / script
输入您的名称:
TEST_NAME
成功

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(){}

公用插槽:
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;
//注意,我们需要添加\n(就像按回车键一样)
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程序= / home / dev / script;

myProcess-> start( / bin / sh,QStringList()<<程序);

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(){}

公用插槽:
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;
//注意,我们需要添加\n(就像按回车键一样)
this-> write(QString( myname + QString( \n))。toLatin1() );
//不需要下一行
// qDebug()<< this-> readAll();
qDebug()<< this-> readAllStandardOutput();

}

int main(int argc,char * argv [])
{
QCoreApplication a(argc,argv);

MyProcess * myProcess = new MyProcess();

QString程序= /home/fran/code/myscript.sh;

myProcess-> start( / bin / sh,QStringList()<<程序);

a.exec();
}

#include main.moc

脚本测试应用程序:

 回显输入您的名字: 
读n
如果[! -z $ n];
然后
echo success
exit 0;
else
echo failed
exit 1;
fi


Noted: this appears to be a specific issue question but hopefully it can be edited for all to related to

I need to interact with a QProcess object.

The Problem:

I am not getting any output from QProcess after calling QProcess:write(input)

More Info:

Going through the doc pages led me to create an example below:

I have a script requesting user input, and finally displaying and appropriate message based on the user input.

Testing:

After adding a "log" feature to my script for testing, the following occurs:

  • script executes
  • script requests user input (confirmed by the 'first' qDebug() << p->readAll())
  • script accepts input from QProcess (confirmed by script 'log output')

After this, no output is received. The following 2 debug statements both fire (i.e. wait 30s each)

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();
}

Followed by:

QString s = QString(p->readAll() + p->readAllStandardOutput());

where s is an empty string.

The issue is s should contain either "success" or "failed"

Calling Code:

QString cmd = QString("sh -c \"/path/to/bashscript.sh\"");
QString input = QString("Name");
QString result = runCommand(cmd, input)

Process 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 I modified the run command as you said, also using the QStringList with the args.

Still does not get output, infact the waitForReadyRead() and waitForFinished() returns false instantly.

Called with:

QString r = runCommand(QString("text"));

Process 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 Output of the Process:

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...

Thoughts on this?

UPDATE 2

@Tarod Thank you for taking the time to make a solution.

It works, however not completely is expected.

I copied over your code, exactly.

Made a few changes in the mReadyReadStandardOutput()

See additional info below.

The problem:

After running the application (and script), I get a result -> AWESOME

Everytime it is the incorrect result i.e. "failed". -> NOT AWESOME

Terminal Output:

void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"enter your name:\n"
""
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"failed\n"
Press <RETURN> to close this window...

script contents:

#!/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 output

myname

running this manually from console:

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

Full 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"

script issue? QProcess issue?

解决方案

Unfortunately I don't have all your code, so I made an example. I hope it helps you.

If I compare my code to yours, I think the problem could be you are not calling readAllStandardOutput() after writing or maybe you are not calling exec() in your main.cpp.

#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"

Script to test the application:

echo "enter your name:"
read n
if [ ! -z "$n" ];
then
    echo "success"
    exit 0;
else
    echo "failed"
    exit 1;
fi

这篇关于在Qt Console应用程序中读写QProcess的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-29 03:03
查看更多