QProcess 类

导读:本篇文章讲解 QProcess 类,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

顺序设备 – QProcess 类(启动进程,与之交互) – 知乎本文结构如下: 概述函数详解准备阶段启动阶段运行阶段退出阶段其他附:所有函数概述QProcess 类的作用就是启动一个程序,然后与之交互。因为和 socket 都是顺序设备类型,所以读写的方式基本大差不差。本文将按照…QProcess 类https://zhuanlan.zhihu.com/p/52116398

QProcess 类的作用就是启动一个程序,然后与之交互。因为和 socket 都是顺序设备类型,所以读写的方式基本大差不差。本文将按照:“准备阶段->启动阶段->运行阶段->退出阶段”的思路来理清如何使用 QProcess 类。

函数详解

准备阶段

指定程序
    获取:QString program() const
    设置:void setProgram(const QString &program)
指定参数
    获取:QStringList arguments() const
    设置:void setArguments(const QStringList &arguments)
Windows专属
    获取:QString nativeArguments() const
    设置:void setNativeArguments(const QString &arguments)
设置 stdout、stderr
    获取:QProcess::ProcessChannelMode processChannelMode() const
    设置:void setProcessChannelMode(QProcess::ProcessChannelMode mode)

既然我们要启动一个程序,当然我们要选择启动哪个程序了,用 setProgram() 函数指定,启动参数用 setArguments() 来设置。

关于 nativeArguments(),这是专门用在 Windows 操作系统上。虽然 Qt 跨平台已经做的很好了,但是在 Windows 系统上,启动外部程序的命令参数会调用 Windows 系统的 API 接口来完成启动,这时候就只能用 setNativeArguments() 来设置启动参数,而不能用 setArguments()。比如说最常见的画图程序,我在“我的文档”中有一个 temp.png 图片,我想通过画图程序来启动,那么代码应该是这样的:

QProcess *process = new QProcess();
process->setWorkingDirectory("C:/Users/ren/Documents");
process->setNativeArguments("temp.png");
process->start("mspaint.exe");
process->waitForFinished();
delete process;

关于 stdout、stderr,任何程序都有一条向外传输信息的标准输出通道,即 stdout,和一条标准错误通道,即 stderr。其中 stdout 传输正常信息,就是我们用 qDebug() 或者 print() 打印的信息,而 stderr 传输错误信息。说“通道”可能不是很好理解,其实就是两个文件,尤其是在万物皆为文件的 Linux 中。程序输出的信息写到这两个文件,然后屏幕去读取。在启动程序前,我们可以用 setProcessChannelMode() 来控制输出通道的行为。通道行为模式如下:

  • (1)SeparateChannels(默认),QProcess 管理这两条通道,为它们分别保存在两个单独的缓冲区中,此时如果想读取通道信息的话需要调用 setReadChannel() 来选择当前读取通道;
  • (2)MergedChannels 模式是将标准错误通道 stderr 合并到 stdout 通道中,原来的 stderr 通道将不会接收任何数据。在这种模式下两种信息会都经过 stdout 通道传输信息;
  • (3)ForwardedChannels 模式就是将启动的程序的 stdout、stderr 信息都从主进程的 stdout、stderr 通道往外输出了;
  • (4)ForwardedErrorChannel 模式就是只将 stderr 信息转发到主进程。最常见的场景就是命令行工具,你看我们用命令行启动一个程序后只看到错误信息,其他的信息都保存到一个文件了;
  • (5)ForwardedErrorChannel 模式就是只将 stdout 信息转发到主进程。

特殊程序的设置

进程环境
    获取:QProcessEnvironment processEnvironment() const
    设置:void setProcessEnvironment(const QProcessEnvironment &environment)
工作目录
    获取:QString workingDirectory() const
    设置:void setWorkingDirectory(const QString &dir)

关于 processEnvironment(),有些程序启动的时候需要必要的环境变量,比如“TMPDIR”为“C:\MyAPP\temp”,或者“PATH”需要某某路径之类的。

关于 workingDirectory(),如果设置了工作目录,那么 QProcess 将在此目录中启动程序。如果没有设置,默认是本程序的目录中启动。

启动阶段

启动

合并式
    void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode = ReadWrite)
    void start(const QString &command, QIODevice::OpenMode mode = ReadWrite)
    void start(QIODevice::OpenMode mode = ReadWrite)
    [static]int execute(const QString &program, const QStringList &arguments)
    [static]int execute(const QString &command)
分离式
    bool startDetached(qint64 *pid = nullptr)
    bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), qint64 *pid = nullptr)
    bool startDetached(const QString &command)
信号
    [signal]void started()

状态

获取:QProcess::ProcessState state() const
信号:[signal]void stateChanged(QProcess::ProcessState      newState)

当一切准备就绪以后,接下来就是启动程序了。启动程序分两种:start() 和 startDetached()

(1)start() 函数

如果在启动前已经用 setProgram() 和 setArguments() 指定了程序和参数,那么直接调用第三种 start() 函数即可启动;如果没有指定,那么调用第一种 start() 时需要将程序和参数传入参数列表中。

关于第二种 start(),这个要区别于第一种和第三种。它的作用是执行一个命令而不是启动一个程序,比如删除某某文件命令“del /s *.txt”,其中 /s 表示从子目录删除指定的文件。如果命令中包含了空格,需要用 \”\” 来包裹住,否则执行不通过。如下所示。为了避免踩各种坑,建议用 setProgram() 和 setArguments() 指定了程序和参数,然后调用第三种 start() 方式。

QProcess process;
process.start("dir \"My Documents\"");

关于 execute() 静态函数,它和 start() 唯一的区别就是:start() 是非阻塞式的,而 execute() 是阻塞式的,即启动后就一直等待程序结束,获得程序的退出代码为止。此时启动的程序的所有输出都转发到调用进程。

(2)startDetached()

用 startDetached() 启动程序后,程序就和调用进程分离了。啥意思?就是说如果用 start() 启动程序,此时如果关闭了调用进程,那么启动的程序也会随之被关闭;如果用 startDetached() 启动的话,即使调用进程关闭,那么启动的程序依然不受影响的继续运行着。

运行阶段

进程ID:qint64 processId() const
重定向到文件
    错误:void setStandardErrorFile(const QString &fileName, QIODevice::OpenMode mode = Truncate)
    输入:void setStandardInputFile(const QString &fileName)
    输出:void setStandardOutputFile(const QString &fileName, QIODevice::OpenMode mode = Truncate)
    [static]QString nullDevice()

关于 processId(),如果有程序再运行,那么该函数返回进程标识符。

关于重定向,就是本来信息输出到标准通道,现在都输出到文件中了。

交互

读取信息
    获取:QProcess::ProcessChannel readChannel() const
    设置:void setReadChannel(QProcess::ProcessChannel channel)
    信号
        [signalvoid readyReadStandardError()
        [signalvoid readyReadStandardOutput()
    读取
        QByteArray readAllStandardError()
        QByteArray readAllStandardOutput()
    关闭:void closeReadChannel(QProcess::ProcessChannel channel)
写入信息
    获取:QProcess::InputChannelMode inputChannelMode() const
    设置:void setInputChannelMode(QProcess::InputChannelMode mode)
    关闭:void closeWriteChannel()
进程A->进程B:void setStandardOutputProcess(QProcess *destination)

关于交互,因为 QProcess 是继承于 QIODevice 的,那么 QIODevice 中的读写函数都可以用在 QProcess 类中。请参考《QIODeivce 类 – 什么是设备?》.

关于 setStandardOutputProcess(),就是将1进程的信息输出到2进程中,例如“command1 | command2”就可以用如下代码表示:

QProcess p1;
QProcess p2; 
p1.setStandardOutputProcess(&p2);
p1.start("command1");
p2.start("command2");

错误

获取:QProcess::ProcessError error() const
信号:[signal]void errorOccurred(QProcess::ProcessError error)

同步进程

bool waitForFinished(int msecs = 30000)
bool waitForStarted(int msecs = 30000)

关于同步进程,因为 QProcess 启动程序是异步的,当需要同步处理程序时就需要 waitFor… 相关的函数。

退出阶段

退出
    void kill()
    void terminate()
退出代码:int exitCode() const
退出状态:QProcess::ExitStatus exitStatus() const
信号:[signal]void finished(int exitCode, QProcess::ExitStatus exitStatus)

关于 kill(),作用是杀死当前进程使之退出。这个函数也是调用平台相关的 API,如在 Windows 上调用 TerminateProcess,而在 Unix 和 macOS 上是将 SIGKILL 信号发送到进程中。

关于 terminate(),区别于 kill() 这种暴力的退出不同,它在退出进程的时候是有机会提示用户输入任何为保存的文件等。在 Windows 上是发送 WM_CLOSE 到进程的顶级窗口,然后发到进程本身的主线程,而 在 Unix 和 macOS 上是发送 SIGTERM 信号。注意在 Windows 上,没有事件循环或者不处理 WM_CLOSE 消息的控制台程序只能调用 kill() 来终止。

其他

Windows相关
    QProcess::CreateProcessArgumentModifier createProcessArgumentsModifier() const
    void setCreateProcessArgumentsModifier(QProcess::CreateProcessArgumentModifier modifier)
    [static]QStringList systemEnvironment()

关于 Windows 相关函数,只能在 Windows 平台上用。

关于 systemEnvironment(),该函数获取系统的“键值对”环境变量,例如“PATH=/usr/bin:/usr/local/bin”、“HOME=/home/greg”等。

附:所有函数

  • 准备阶段
    • 指定程序
      • 获取:QString program() const
      • 设置:void setProgram(const QString &program)
    • 指定参数
      • 获取:QStringList arguments() const
      • 设置:void setArguments(const QStringList &arguments)
      • Windows专属
        • 获取:QString nativeArguments() const
        • 设置:void setNativeArguments(const QString &arguments)
    • 设置 stdout、stderr
      • 获取:QProcess::ProcessChannelMode processChannelMode() const
      • 设置:void setProcessChannelMode(QProcess::ProcessChannelMode mode)
    • 特殊程序的设置
      • 进程环境
        • 获取:QProcessEnvironment processEnvironment() const
        • 设置:void setProcessEnvironment(const QProcessEnvironment &environment)
      • 工作目录
        • 获取:QString workingDirectory() const
        • 设置:void setWorkingDirectory(const QString &dir)
  • 启动阶段
    • 启动
      • 合并式
        • void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode = ReadWrite)
        • void start(const QString &command, QIODevice::OpenMode mode = ReadWrite)
        • void start(QIODevice::OpenMode mode = ReadWrite)
        • [static]int execute(const QString &program, const QStringList &arguments)
        • [static]int execute(const QString &command)
      • 分离式
        • bool startDetached(qint64 *pid = nullptr)
        • bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), qint64 *pid = nullptr)
        • bool startDetached(const QString &command)
      • 信号
        • [signal]void started()
    • 状态
      • 获取:QProcess::ProcessState state() const
      • 信号:[signal]void stateChanged(QProcess::ProcessState newState)
  • 运行阶段
    • 进程ID:qint64 processId() const
    • 重定向到文件
      • 错误:void setStandardErrorFile(const QString &fileName, QIODevice::OpenMode mode = Truncate)
      • 输入:void setStandardInputFile(const QString &fileName)
      • 输出:void setStandardOutputFile(const QString &fileName, QIODevice::OpenMode mode = Truncate)
      • [static]QString nullDevice()
    • 交互
      • 读取信息
        • 获取:QProcess::ProcessChannel readChannel() const
        • 设置:void setReadChannel(QProcess::ProcessChannel channel)
        • 信号
          • [signalvoid readyReadStandardError()
          • [signalvoid readyReadStandardOutput()
        • 读取
          • QByteArray readAllStandardError()
          • QByteArray readAllStandardOutput()
        • 关闭:void closeReadChannel(QProcess::ProcessChannel channel)
      • 写入信息
        • 获取:QProcess::InputChannelMode inputChannelMode() const
        • 设置:void setInputChannelMode(QProcess::InputChannelMode mode)
        • 关闭:void closeWriteChannel()
      • 进程A->进程B:void setStandardOutputProcess(QProcess *destination)
    • 错误
      • 获取:QProcess::ProcessError error() const
      • 信号:[signal]void errorOccurred(QProcess::ProcessError error)
    • 同步进程
      • bool waitForFinished(int msecs = 30000)
      • bool waitForStarted(int msecs = 30000)
  • 退出阶段
    • 退出
      • void kill()
      • void terminate()
    • 退出代码:int exitCode() const
    • 退出状态:QProcess::ExitStatus exitStatus() const
    • 信号:[signal]void finished(int exitCode, QProcess::ExitStatus exitStatus)
  • 其他
    • Windows相关
      • QProcess::CreateProcessArgumentModifier createProcessArgumentsModifier() const
      • void setCreateProcessArgumentsModifier(QProcess::CreateProcessArgumentModifier modifier)
    • [static]QStringList systemEnvironment()

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/96468.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!