QProcess的正确用法

算法吟游者
• 阅读 2056

  在进行编程过程中,经常用到在程序当中调用其它的程序,这就需要用到进程调用,在QT中就用到了QProcess的进行进程调用,其有QT自身的特点,用起来非常方便,与C++本身的接口不一样,其流程特点如下:

特点1:需要waitForStarted,判断程序启动是成功,还是失败

特点2:需要waitForFinished,判断程序是否结束

这也是比较传统的用法,当然,你不愿意判断结束,就可以不判断了。

一般使用时容易犯的错误,就是直接省略了特点1的处理过程,进行了特点2,正常的话,是没问题,然则被调用的程序出问题的话,那就难查找原因了,如下:

//QProcess的用法
void MainWindow::on_pushButton_2_clicked()
{
    qDebug()<<"enter function MainWindow::on_pushButton_2_clicked";
    QProcess myProcess;
    QStringList arguments;
    arguments += "1";
    arguments += "2";
    myProcess.start("./test", arguments);
    myProcess.closeReadChannel(QProcess::StandardOutput);
    myProcess.closeReadChannel(QProcess::StandardError);
    myProcess.closeWriteChannel();

    while(!myProcess.waitForFinished(500))
    {
        qDebug()<<"wait";
        sleep(2);
        QCoreApplication::processEvents(QEventLoop::AllEvents, 2000);
    }
    qDebug()<<"exit function MainWindow::on_pushButton_2_clicked";
}

上面代码看着是没问题的,正常是可以执行的,我专门测试了一个异常的情况,就是上面的./test程序是不存在的,执行情况如下:

enter function MainWindow::on_pushButton_2_clicked
wait
wait
wait
wait
wait
wait
wait
wait

发现了,程序进入了死循环,你也不知道什么原因,是不是,有些蒙了

原因是,程序启动就失败了,这时waitForFinished()函数会一直返回false,官方也有相应的说明:

Returns true if the process finished; otherwise returns false (if the operation timed out, if an error occurred, or if this QProcess is already finished)

说的很明白,如果进程已经结束了,会一直返回false,所以上面就进入了死循环。
那怎么解决呢?
下面就说说QProcess的标准流程了,如下:

//QProcess的用法
void MainWindow::on_pushButton_2_clicked()
{
    qDebug()<<"enter function MainWindow::on_pushButton_2_clicked";
    QProcess myProcess;
    QStringList arguments;
    arguments += "1";
    arguments += "2";
    myProcess.start("./test", arguments);
    myProcess.closeReadChannel(QProcess::StandardOutput);
    myProcess.closeReadChannel(QProcess::StandardError);
    myProcess.closeWriteChannel();

    if(myProcess.waitForStarted())
    {
        qDebug()<<"启动成功";
    }
    else
    {
        qDebug()<<"启动失败 error:"<<myProcess.errorString();
        return;
    }

    while(!myProcess.waitForFinished(500))
    {
        qDebug()<<"wait";
        sleep(2);
        QCoreApplication::processEvents(QEventLoop::AllEvents, 2000);
    }
    qDebug()<<"exit function MainWindow::on_pushButton_2_clicked";
}

这样再执行,输出如下:

enter function MainWindow::on_pushButton_2_clicked
启动失败 error: "Process failed to start: 系统找不到指定的文件。"

这样的话,就知道错误了,也不会进入死循环了,这也说明,如果想得到程序返回的结果,waitForStarted()与waitForFinished()两个函数都不可少。

点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
strace命令使用
命令介绍strace是Linux环境下的一款程序调试工具,用来输出一个应用程序所使用的系统调用。strace底层使用内核的ptrace特性来实现其功能。什么是系统调用?系统调用是通向操作系统本身的接口,是面向底层硬件的。通过系统调用,可以使得用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互,是操作系统留给
good123 good123
3年前
前端的路由封装
在一个项目当中,我们常常需要调用很多接口,我们不可能每次调用接口都完整地写一遍调用,因此我们需要对其进行封装/axios.js///封装axiosimportaxiosfrom"axios";importqsfrom"qs";//初始化axios,设置默认的baseURLconsthttpaxios.create(baseUR
并发编程
并发编程笔记本博客根据学习而做的笔记,链接如下一、基本概念1、进程与线程进程程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理IO的。当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。进程
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
Qt类库介绍
QT类库QT核心特点QT是一个跨平台开发的类库。QT的元对象编译器MOC是一个预处理器,在源程序被编译前先将这些QT特性的程序转为标准的C兼容的形式,然后再有标准的C编译器进行编译。也就是为什么在使用信号和槽的机制的类里,必须添加一个Q\_OBJECT宏的原因,只有添加了这个宏,moc才能对类里的信号与槽代码进
Stella981 Stella981
3年前
QT中调用外部程序:QProcess的使用
!运行:ipconfig(http://static.oschina.net/uploads/img/201406/06143054_WauU.png"QT中调用外部程序:QProcess的使用lucienlucien_cc的博客")!运行:pingwww.baidu.com(http://static.oschina.net/
Stella981 Stella981
3年前
Linux fork() 系统调用
    在Linux中,当程序调用fork()函数时,系统会创建新的进程,为其分配资源(存储数据和代码的空间),然后把原来进程的所有值都复制到新进程中,只有少量数值与原来的进程值不同,相当于复制了本身。      fork()系统调用,被调用一次,却能返回两次:父进程和子进程各自返回一次。可以通过fork()的返回值的不同来区分父进程和子进程。
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Linux应急响应(四):盖茨木马
0x00前言Linux盖茨木马是一类有着丰富历史,隐藏手法巧妙,网络攻击行为显著的DDoS木马,主要恶意特点是具备了后门程序,DDoS攻击的能力,并且会替换常用的系统文件进行伪装。木马得名于其在变量函数的命名中,大量使用Gates这个单词。分析和清除盖茨木马的过程,可以发现有很多值得去学习和借鉴的地方。0x01应急场景
Wesley13 Wesley13
3年前
VC++知识点整理
1.内联函数定义:定义在类体内的成员函数,即函数的函数体放在类体内特点:在调用处用内联函数体的代码来替换,用于解决程序的运行效率问题。一定要在调用之前定义,并且内联函数无法递归调用。2.构造函数与析构函数构造函数:用于为对象分配内存空间,对类的成员变量进行初始化,并执行其他内部管理操作。可以接受参