QProcess简介
QProcess可以用于启动外部程序,它提供了一系列函数来启动、控制和与外部进程进行交互。
作用:
- 启动外部进程: 通过start函数
- 进程状态和控制:判断进程是否正在运行、等待进程完成、终止进程等。如stateChanged信号
- 进程通信: 支持与外部进程进行通信。可以通过管道(标准输入、标准输出和标准错误输出)进行输入和输出操作。readyReadStandardOutput信号
- 信号和槽机制:QProcess使用信号和槽机制来处理与外部进程相关的事件。例如,当外部进程完成时,可以使用finished信号来通知应用程序。
进程id:
qint64 processId() const;
启动进程
一体式:
以子进程的方式启动外部程序,外部进程与主程序互不干扰,但外部进程的父进程就是主程序。
当主程序退出时,被主程序调用起来的进程也退出。
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode = ReadWrite)
void start(QIODevice::OpenMode mode = ReadWrite)
program:启动外部应用程序的路径。不包含空格,包含空格需要在arguments中传入
arguments:传入待启动外部程序的参数,即:int main(int argc, char *argv[])这里的参数。
如果在启动前已经用 setProgram() 和 setArguments() 指定了程序和参数,那么直接调用第二种 start() 函数即可启动;如果没有指定,那么调用第一种 start() 时需要将程序和参数传入参数列表中。
分离式:
以分离的方式启动外部程序,外部程序与主程序互不干扰,外部进程的父进程是系统的 init 进程。
外部程序启动程序后,主程序退出时,被调用的进程继续执行,不退出。
static bool startDetached(const QString &program, const QStringList &arguments,
const QString &workingDirectory = QString() , qint64 *pid = nullptr);
调⽤start()函数或open()函数启动进程。在程序启动后,QProcess进⼊运⾏状态并发出started()信号
//启动完毕
connect(process, &QProcess::started, this, [=]()
{
qDebug() << "started:" ;
});
execute():
以阻塞的方式启动外部程序,只有外部程序执行完成后,主程序才会继续执行。外部程序的标准输出、标准错误都是重定向到主程序的标准输出和标准错误的。
退出进程
void kill()
void terminate()
kill(),作用是杀死当前进程使之退出。这个函数也是调用平台相关的 API,如在 Windows 上调用 TerminateProcess,而在 Unix 和 macOS 上是将 SIGKILL 信号发送到进程中。
terminate(),区别于 kill() 这种暴力的退出不同,它在退出进程的时候是有机会提示用户输入任何为保存的文件等。在 Windows 上是发送 WM_CLOSE 到进程的*窗口,然后发到进程本身的主线程,而 在 Unix 和 macOS 上是发送 SIGTERM 信号。注意在 Windows 上,没有事件循环或者不处理 WM_CLOSE 消息的控制台程序只能调用 kill() 来终止。
当进程退出时,QProcess重新进⼊NotRunning状态(初始状态),并发出finish()信号。
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [=](int exitCode, QProcess::ExitStatus exitStatus)
{
if (exitStatus == QProcess::NormalExit) {
qDebug() << "Process finished with exit code:" << exitCode;
}
else {
qDebug() << "Process crashed!";
}
});
同步进程
waitForStarted()函数——阻塞直到进程开始。
waitForReadyRead()函数——阻塞直到有新数据可在当前读取通道上读取为⽌。
waitForBytesWritten()函数——阻塞直到将⼀个有效载荷数据写⼊该进程为⽌。
waitForFinished()函数——阻塞直到过程完成。
通道通信
进程具有两个预定义的输出通道:
标准输出通道(stdout)提供常规控制台输出。
标准错误通道(stderr)通常提供由进程打印的错误。
进程的输出通道与QProcess的读取通道相对应,⽽进程的输⼊通道与QProcess的写⼊通道相对应。这是因为我们使⽤QProcess读取的内容是进程的输出,⽽我们编写的内容则成为进程的输⼊。
当有新的标准输出数据可⽤时,它也会发出readyReadStandardOutput()信号,⽽当有新的标准错误数据可⽤时,它会发出readyReadStandardError()信号。
connect(process, &QProcess::readyReadStandardOutput, this, [=]()
{
QString qstr(process->readAllStandardOutput());
qDebug() << "readyReadStandardOutput:" << qstr;
});
QByteArray readAllStandardOutput(); //标准输出通道信息
QByteArray readAllStandardError(); //标准错误通道信息
延伸:如在windows系统上使用QProcess类来判断特定进程是否正在运行
bool isProcessRunning(const QString& processName)
{
QProcess process;
process.start("tasklist", QStringList() << "/FI" << "IMAGENAME eq " + processName);
process.waitForFinished();
QString output = process.readAllStandardOutput();
QStringList processes = output.split("\n");
processes.removeFirst(); // 移除第一行标题
foreach(QString line, processes) {
if (line.contains(processName))
return true;
}
return false;
}
延伸:获取环境变量
#include <QCoreApplication>
#include <QProcessEnvironment>
#include <QString>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
// 获取环境变量"PATH"的值
QString path = env.value("PATH");
qDebug() << "PATH:" << path;
return a.exec();
}
进程的状态
enum ProcessState {
NotRunning,
Starting,
Running
};
获取进程的状态:
QProcess::ProcessState state() const;
进程状态改变的信号
进程状态改变,会发出该信号
void stateChanged(QProcess::ProcessState state, QPrivateSignal);
connect(process, &QProcess::stateChanged, this, [=](QProcess::ProcessState state)
{
qDebug() << "show state:";
switch (state)
{
case QProcess::NotRunning:
qDebug() << "Not Running";
break;
case QProcess::Starting:
qDebug() << "Starting";
break;
case QProcess::Running:
qDebug() << "Running";
break;
default:
qDebug() << "otherState";
break;
}
});