QT通过QProcess执行终端命令并实时输出回显

QT通过QProcess执行终端命令并实时输出回显

  • 引子

在QT程序中我们经常需要与其他的程序间进行交互,而与终端进行交互就是一个例子。在不需要获取返回信息的情况下我们可以直接使用”system()”函数执行,但是当需要获取执行的结果或者需要实时地将结果输出到窗口上时,就比较难办了,需要涉及进程管道等等。而QT提供的QProcess类则大大简化了这一过程。

QProcess是QT提供的与外部程序进行交互的一个类,主要使用到以下的函数:

start();     //启动一个进程
kill();         //关闭启动的外部进程
write();     //向外部进程写入数据
readAllStandardOutput();     //读取外部进程的标准输出
readAllStandardError();        //读取外部进程的错误信息
  • 创建QProcess对象并连接信号与槽
cmd = new QProcess(this);
connect(cmd , SIGNAL(readyReadStandardOutput()) , this , SLOT(on_readoutput()));
connect(cmd , SIGNAL(readyReadStandardError()) , this , SLOT(on_readerror()));
  • 实现槽函数

接收到标准输出:

void MainWindow::on_readoutput()
{
    ui->textEdit->append(cmd->readAllStandardOutput().data());   //将输出信息读取到编辑框
}

接收到错误信息:

void MainWindow::on_readerror()
{
    QMessageBox::information(0, "Error", cmd->readAllStandardError().data());    //弹出信息框提示错误信息
}
  • 启动外部程序并写入数据
cmd->start("bash");             //启动终端(Windows下改为cmd)
cmd->waitForStarted();        //等待启动完成
cmd->write("ls\n");               //向终端写入“ls”命令,注意尾部的“\n”不可省略

没有意外的话在编辑框中将看见输出了当前目录下的文件:

同理,可以执行绝大部分在终端中执行的命令,不过有些程序所需要的实现可能不太一样,比如更新软件包,则需执行如下命令:

sudo -S apt-get update

如果不带参数”-S”,则会返回错误信息:“sudo:没有终端存在,且未指定askpass程序”

因此此种方法启动程序的时候如果需要root权限,则需要在”sudo”后加上选项”-S”。

还有的情况就是因为终端启动的时候其实已经帮我们读取了很多环境变量,但是我们在QT程序中直接启动bash的时候这些环境变量尚未被读取,导致一些程序无法启动,报错“未找到命令”。这时需要我们主动去source一遍对应的环境。

  • 善后

QProcess启动的外部程序并不会随着QT程序的关闭而关闭,所以在窗口的销毁函数中加入以下代码,使得窗口销毁时连带终结外部进程。

if(cmd)
{
      cmd->close();
      cmd->waitForFinished();
}
  • 写在最后

代码只是关键部分的代码,还有头文件中的声明、槽函数的声明等等一些琐碎细节的地方没有写出在文中,还请自行添加。同时为了方便你们参照,我也将工程上传了一份到GitHub中,如有不懂之处,可参照我的GitHub上的代码:QProcess_Examples-字节莫的GitHub

如有问题欢迎留言讨论。

欢迎关注公众号「字节莫」,探讨更多技术、人文的思考,一起进步!

点击量:810

One Comments “QT通过QProcess执行终端命令并实时输出回显
  1. winger说道:

    good job。 thx share !

发表评论

电子邮件地址不会被公开。 必填项已用*标注