引言

随着需求的更新、程序的逐渐壮大,现在需要在应用程序中调用外部编译器,执行相关指令并获得结果。
由于Qt中使用的是C++语言,自然可以调用system去执行相关指令,但是在使用过程中发生了乱码,导致运行之后程序报错。
后来发现Qt自带的类,QProcess,毫不犹豫转到这个上面来,但是一开始还是因为不熟悉浪费了很多时间,所以想要自己整理一下思路,因为英文文档比较难读懂,所以在此尽可能多的讲解怎么使用那些常用的API,以后还会更新。

开始

Qt提供了QProcess类,这使得我们可以在应用程序中启动一个外部程序并与之交互通信。主要包括了三种启动外部命令的方式:

QProcess::start()

特点:非阻塞、一体式

void QProcess::start(const QString & program, const QStringList & arguments, OpenMode mode = ReadWrite)

使用这样的启动方式之启动外部程序启动后,它会随着主程序的退出而退出。

QProcess::startDetached()

特点:分离式

void QProcess::startDetached(const QString & program, const QStringList & arguments, const QString & workingDirectory = QString(), qint64 * pid = 0)

外部程序启动后,当主程序退出时并不退出,而是继续运行。

QProcess::execute()

特点:阻塞

获取返回值
int QProcess::execute()
int QProcess::exitCode()
读取输出/到文件
// 从标准输出通道中读取数据
readAllStandardOutput()
// 从标准错误通道中读取数据
readAllStandardErrot()
// 设置输出到的文件,相当于前面的重定向
setStandardOutputFile()
// 设置错误到的文件
setStandardErrorFile()
// 读取标准输出
read()
readLine()
同步进程

QProcess提供了完成同步操作的函数:

以下方法会导致进程阻塞,直到符合其中的某一状态:

// 外部程序启动完毕
waitForStarted()
// 输出通道中的新数据是可读的
waitForReadyRead()  
// 输入通道中的数据被写入完毕
waitForBytesWritten() 
// 外部程序执行完毕
waitForFinished()  

另外要注意的是,如果在主线程(QApplication::exec())中调用这些函数,可能会造成当前用户界面不响应1

终止
QProcess::kill()
QProcess::terminate()
QProcess::close()
注意

启动外部程序必须要传递外部程序的路径和运行參数。參数用QStringList来带入。

官方提供了分别设置路径或者参数的方法,可疑单独设置,也可以在一个方法中直接以参数的形式传入。

设置路径:

void QProcess::setProgram(const QString & program)

设置參数[可选]:

void QProcess:: setArguments(const QStringList & arguments)

示例

QObject *parent;
...
QString program = "./path/to/Qt/examples/widgets/analogclock";
QStringList arguments;
arguments << "-style" << "fusion";

QProcess *myProcess = new QProcess(parent);
myProcess->start(program, arguments);
空格

当使用字符串传入一个整体命令之后,如果字符串中间有空格或者路径中文件夹中有空格,都是会失败的。
比如:

// 路径中带有空格,失败
process->start("C:/Program Files/execute.exe");

// 路径中有空格,但是使用传入字符串列表的argument,成功
process->start("C:/Program Files/execute.exe", QStringList("C:/Program Files/HaoZip/HaoZip.exe"));

// 或者传入空字符串,成功
QString wordPath = "C:\\Program Files\\Microsoft Office\\Office12\\WINWORD.EXE"
process->start(wordPath, QStringList() << "");

以上后两种方式成功是因为,如果使用单参数,并且路径中包含一个空格,则空格后的字符将被视为传递给可执行文件的参数。将两个参数重载,例如与空字符串一起使用,可以指定第一个参数是可执行文件的完整路径,即使它包含空格,并且后面的参数严格地作为第二个参数传递。

// 使用;或者&&同时执行两个语句,失败
process->start("ls -a && ifconfig"));

// 使用字符串列表传入目标程序目录,成功
QProcess *process = new QProcess(this);
QString program = "explorer.exe";
QString folder = "C:\\";
process->start(program, QStringList() << folder);

必要的时候某些程序需要有特定的环境来能执行,通过setEnvironment()来环境变量设置,setWorkingDirectory()来设置工作目录,默认的工作路径是当前调用程序的工作路径。

例如以下程序可以实现在输入框中输入命令,点击pushButton按钮打开cmd命令行控制台执行命令的功能。2

void MainWindow::on_pushButton_clicked()
{
    ui->textEdit->clear();
    QProcess process(this);
    process.setProgram("cmd");
    QStringList argument;
    argument<<"/c"<<ui->lineEdit->text();
    process.setArguments(argument);
    process.start();
    process.waitForStarted(); //等待程序启动
    process.waitForFinished();//等待程序关闭
    QString temp=QString::fromLocal8Bit(process.readAllStandardOutput()); //程序输出信息
    ui->textEdit->setText(temp);
}

  1. 引用↩︎

  2. 小示例 ↩︎

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐