qt QProcess学习

时间:2024-03-29 07:23:20
QProcess简介

QProcess可以用于启动外部程序,它提供了一系列函数来启动、控制和与外部进程进行交互。

作用:

  1. 启动外部进程: 通过start函数
  2. 进程状态和控制:判断进程是否正在运行、等待进程完成、终止进程等。如stateChanged信号
  3. 进程通信:  支持与外部进程进行通信。可以通过管道(标准输入、标准输出和标准错误输出)进行输入和输出操作。readyReadStandardOutput信号
  4. 信号和槽机制: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;

}

});