QT核心模块QtCore功能详细说明,QProcess类(六)

目录

一. 核心数据类型 (Core Datatypes)

二. 文件和目录 (File and Directory Handling)

三. 事件系统 (Event System)

QObject 

QCoreApplication、QEventLoop、QEvent、QMetaObject

四. 多线程和并发 (Multithreading and Concurrency)

五. 国际化和本地化 (Internationalization and Localization)

六. 进程和进程间通信 (Process and Inter-Process Communication - IPC)

QProcess

常见使用场景

核心概念说明

主要方法和函数

启动进程

与进程交互

获取进程信息

控制进程

设置进程环境/通道模式

主要信号

进程通道模式详解

同步与异步执行

高级用法

​错误处理

测试代码

案例 1:基础使用 - 运行简单命令并获取输出

案例 2:交互式命令 - 实时读取和输入

案例 3:错误处理与状态监控 - 编译代码并分析结果

案例 4:管道与通道自定义 - 多进程协作

案例 5:与网络结合 - 远程命令执行服务

QSharedMemory

QSystemSemaphore

QLocalServer 和 QLocalSocket

七. 插件支持 (Plugin Support)

八. 文本编解码 (Text Codecs)

九. 动态库加载 (Dynamic Library Loading)

十. 全局函数

十一. 其他实用工具


一. 核心数据类型 (Core Datatypes)

请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(一)

二. 文件和目录 (File and Directory Handling)

 请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(二)

三. 事件系统 (Event System)

QObject 

请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(三)

QCoreApplication、QEventLoop、QEvent、QMetaObject

请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(四)

四. 多线程和并发 (Multithreading and Concurrency)

 请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(五)

五. 国际化和本地化 (Internationalization and Localization)

  • QLocale
    QLocale 类用于管理语言、区域设置等本地化信息,能够根据不同的区域设置显示日期、时间、数字等格式。

  • QTranslator
    QTranslator 用于加载翻译文件,以便将应用程序界面翻译成不同的语言。

六. 进程和进程间通信 (Process and Inter-Process Communication - IPC)

QProcess

QProcess 用于启动和管理外部进程,扩展 Qt 程序功能并实现与操作系统的交互,也是 是 Qt Core 模块中连接应用程序与外部系统的重要组件,与信号槽机制深度整合。

  • 常见使用场景

     调用命令行工具、集成外部应用程序、执行耗时任务、 自动化任务、获取系统信息。
  • 核心概念说明

    • 外部进程 (External Process)

      外部进程是指由 QProcess 在操作系统中启动的独立程序或命令,例如一个可执行文件(.exe)、脚本(.sh、.py)或系统命令(ls、dir)。

    • 标准输入 (Standard Input, stdin)

      标准输入(stdin)是外部进程接收数据的通道,通常来自键盘或程序提供的输入。在 QProcess 中,可以通过 write() 或 writeData() 方法向外部进程的 stdin 发送数据。

    • 标准输出 (Standard Output, stdout)

      标准输出(stdout)是外部进程生成的主要输出通道,包含程序的执行结果或日志信息。通过 readAllStandardOutput() 或信号 readyReadStandardOutput() 读取 stdout 数据。

    • 标准错误 (Standard Error, stderr)

      标准错误(stderr)是外部进程用于输出错误信息或诊断信息的独立通道,与 stdout 分开。通过 readAllStandardError() 或信号 readyReadStandardError() 获取 stderr 数据。

    • 退出代码 (Exit Code)

      退出代码是外部进程结束时返回的整数值,用于指示其执行结果。0 表示成功,非 0 表示某种错误或异常。通过 exitCode() 方法获取退出代码,帮助判断进程是否正常完成。

    • 退出状态 (Exit Status)

      退出状态(Exit Status)描述进程终止的方式,通常有两种:正常退出(Normal Exit)和异常终止(Crashed,例如崩溃或被强制终止)。

    • 进程 ID (Process ID, PID)

      进程 ID(PID)是操作系统分配给每个运行进程的唯一标识符,用于区分不同的进程。

    • 进程状态 (Process State)

      进程状态表示外部进程的当前运行阶段,包括未启动(NotRunning)、启动中(Starting)和运行中(Running)。

    • 工作目录 (Working Directory)

      工作目录是外部进程执行时所在的默认文件系统路径,影响相对路径的解析。可以通过 setWorkingDirectory() 设置工作目录。

    • 环境变量 (Environment Variables)

      环境变量是一组键值对,定义了外部进程运行时的环境设置,例如 PATH、HOME 或自定义变量。在 QProcess 中,可以通过 setProcessEnvironment() 或 setEnvironment() 配置环境变量,以影响进程的行为。

    • 进程通道模式 (Process Channel Mode)

      进程通道模式定义了 QProcess 如何处理外部进程的输入输出通道(stdin、stdout、stderr)。

  • 主要方法和函数

    • 启动进程
      • start(const QString &program, const QStringList &args, OpenMode mode ):​​​​

        • 用于以异步方式启动外部进程。

        • program:要运行的可执行程序路径或命令(如 "notepad.exe" 或 "ls")。

        • arguments:传递给程序的参数列表(QStringList 类型)。

        • mode:输入输出通道的打开模式,默认是 ReadWrite,表示可以读写 stdin、stdout 和 stderr。

      • execute(const QString &program, const QStringList &arguments = QStringList()):
        • 用于以同步方式运行外部进程。它会阻塞调用线程,直到进程执行完成并返回退出代码。

        • program:要运行的程序路径或命令。

        • arguments:传递的参数列表(可选)。

        • 返回值:进程的退出代码(成功通常为 0,失败为非 0)。

      • startDetached(const QString &program, const QStringList &args, const QString &workingDirectory = QString(), qint64 *pid = nullptr);
        • 用于以分离(detached)模式启动外部进程。启动后,进程独立于 QProcess 和调用程序运行,即使父程序退出,子进程也不会受影响。

        • program:要运行的程序路径或命令。

        • arguments:传递的参数列表。

        • workingDirectory:进程的工作目录(可选)。

        • pid:返回进程的 PID(可选)。

        • 返回值:成功启动返回 true,否则返回 false。

      • 总结对比启用方法

        方法

        执行方式

        交互性

        控制权

        典型场景

        start()

        异步

        支持读写

        可控

        实时交互的命令行工具

        execute()

        同步

        无交互

        无需后续管理

        一次性命令执行

        startDetached()

        异步

        无交互

        无控制

        独立运行的外部应用程序

    • 与进程交互
      QProcess 提供了多种方法来与外部进程进行交互,包括向进程写入数据(输入)和从进程读取数据(输出或错误)。
      • write(const QByteArray &data):

        • 用于向外部进程的标准输入(stdin)写入数据。通过它,开发者可以向进程发送命令或数据,模拟用户输入。

        • data:要写入的字节数组(QByteArray 类型)。

        • 返回值:成功写入的字节数,失败返回 -1。

        • 异步写入:数据写入后立即返回,不等待进程处理。

        • 配合信号:通常与 readyRead() 信号结合使用,以读取响应。

      • closeWriteChannel():

        • 用于关闭 QProcess 的标准输入通道(stdin)。关闭后,无法再通过 write() 向进程写入数据,通常用于通知进程输入已结束。

        • 单向关闭:仅关闭 stdin,不影响 stdout 或 stderr 的读取。

        • 不可逆:关闭后无法重新打开 stdin。

      • ​​​​​​​readAllStandardOutput()

        • 读取外部进程标准输出(stdout)中所有当前可用的数据,返回一个字节数组。

        • 一次性读取:读取当前缓冲区中的所有 stdout 数据。

        • 非阻塞:如果没有数据,返回空字节数组。

        • 配合信号:常与 readyReadStandardOutput() 信号一起使用,避免遗漏数据。

      • readAllStandardError()

        • 读取外部进程标准错误(stderr)中所有当前可用的数据,返回一个字节数组。

        • 独立通道:专门读取 stderr,与 stdout 分开。

        • 错误诊断:用于捕获进程执行中的错误或警告。

        • 配合信号:可与 readyReadStandardError() 信号结合,实时处理错误。

      • readChannel()

        • 从当前设置的读取通道(stdout 或 stderr)读取数据。

        • 手动控制:需要提前通过 setReadChannel() 指定通道。

      • setReadChannel(QProcess::ProcessChannel channel)

        • 用于设置当前读取通道,决定后续 readChannel() 调用从 stdout 还是 stderr 读取数据。

        • channel:枚举值,QProcess::StandardOutput(stdout)或 QProcess::StandardError(stderr)。

      • 交互的核心能力说明:

        • 输入:write() 和 closeWriteChannel() 控制 stdin。

        • 输出:readAllStandardOutput() 和 readAllStandardError() 分别读取 stdout 和 stderr。

        • 灵活读取:readChannel() 和 setReadChannel() 提供动态通道管理。

    • 获取进程信息
      QProcess 提供了多种方法来获取外部进程的运行状态和相关信息,包括进程状态、ID、退出码、错误信息以及运行环境等。这些方法帮助开发者监控和管理进程的生命周期。
      • ​​​​​​state():

        • ​​​​​​​返回外部进程的当前状态,反映其生命周期阶段。

        • QProcess::NotRunning:进程未启动或已结束。

        • QProcess::Starting:进程正在启动但尚未完全运行。

        • QProcess::Running:进程正在运行。

      • pid()​​​​​​​返回外部进程的进程 ID(PID),即操作系统分配给该进程的唯一标识符。

      • exitCode() :返回外部进程的退出代码,通常 0 表示成功,非 0 表示失败。

      • exitStatus() :返回进程的退出状态,指示进程是正常结束还是异常终止。

        • QProcess::NormalExit:进程正常退出。

        • QProcess::CrashExit:进程异常终止(如崩溃)。

      • error() :返回启动或运行进程时发生的错误类型, QProcess::ProcessError 枚举值。

        • QProcess::FailedToStart:进程启动失败(如文件不存在)。

        • QProcess::Crashed:进程运行时崩溃。

        • QProcess::Timedout:操作超时。

        • QProcess::ReadError/WriteError:读写错误。

        • QProcess::UnknownError:未知错误。

      • workingDirectory() 返回进程当前的工作目录,即进程执行时的默认文件路径。

      • environment() 返回进程运行时的环境变量列表,(如 "PATH=/usr/bin")。

      • 全面的进程信息获取能力:

        • 状态与标识:state() 和 pid() 监控运行状态和 ID。

        • 退出信息:exitCode() 和 exitStatus() 分析结束情况。

        • 错误处理:error() 诊断问题。

        • 环境信息:workingDirectory() 和 environment() 获取运行上下文。

    • 控制进程
      ​​​​​​​QProcess 提供了多种方法来控制外部进程的生命周期和行为,包括终止进程、等待特定事件(如启动、数据可读或结束)。​​​​​​​
      • kill() 强制终止外部进程,立即无条件结束进程,不给进程清理资源的机会。

      • terminate()

        • 请求外部进程优雅地终止,通常通过发送终止信号(如 SIGTERM),允许进程在结束前执行清理操作。

        • 优雅退出:给进程机会保存数据或释放资源。

        • 不确定性:进程可能忽略终止请求,导致未结束。

      • waitForStarted(int msecs = 30000) 

        • 阻塞当前线程,直到外部进程成功启动或超时。

        • msecs:超时时间(毫秒),默认 30 秒。

        • 返回值:true 表示启动成功,false 表示失败或超时。

      • waitForReadyReadStandardOutput(int msecs = 30000)

        • ​​​​​​​阻塞当前线程,直到进程的标准输出(stdout)有数据可读或超时。

        • msecs:超时时间(毫秒),默认 30 秒。

        • 返回值:true 表示有数据可读,false 表示超时或错误。

      • waitForReadyReadStandardError(int msecs = 30000)

        • 阻塞当前线程,直到进程的标准错误(stderr)有数据可读或超时。

        • msecs:超时时间(毫秒),默认 30 秒。

        • 返回值:true 表示有数据可读,false 表示超时或错误。

      • waitForFinished(int msecs = 30000)

        • 阻塞当前线程,直到外部进程结束或超时。它用于等待进程完成整个执行流程。

        • msecs:超时时间(毫秒),默认 30 秒,-1 表示无限等待。

        • 返回值:true 表示进程结束,false 表示超时。

        • 结果获取:结束后可通过 exitCode() 和 exitStatus() 获取信息。

      • 全面控制能力:

        • 终止控制:kill() 强制结束,terminate() 请求结束。

        • 等待机制:waitForStarted() 确认启动,waitForReadyReadStandardOutput() 和 waitForReadyReadStandardError() 等待输出,waitForFinished() 等待结束。

    • 设置进程环境/通道模式
      ​​​​QProcess 提供了方法来配置外部进程的运行环境,包括工作目录和环境变量。进程通道模式定义了 QProcess 如何处理外部进程的标准输出(stdout)和标准错误(stderr)通道。
      • setWorkingDirectory(const QString &dir)
        • ​​​​​​​​​​​​​​设置外部进程的工作目录,即进程运行时的当前目录。
        • dir:工作目录的绝对路径(QString 类型)。

        • 必须在启动前设置:只有在调用 start() 之前设置才生效。

        • 可查询:通过 workingDirectory() 获取当前值。

      • setEnvironment(const QStringList &environment)
        • 设置外部进程的环境变量列表,覆盖默认继承的环境变量。
        • environment:环境变量列表,每项为 "key=value" 格式的字符串。

        • 启动前设置:必须在 start() 之前调用。

      • setProcessEnvironment(const QProcessEnvironment &environment)
        • 设置外部进程的环境变量,使用 QProcessEnvironment 对象。

        • environment:QProcessEnvironment 对象,包含环境变量的键值对。

          • env.insert("MY_VAR", "test"); // 添加或修改变量
          • env.remove("UNWANTED_VAR");   // 删除变量
      • setProcessChannelMode(QProcess::ProcessChannelMode mode)
        • ​​​​​​​设置进程的通道模式,决定 stdout 和 stderr 的处理方式。
        • mode:枚举值,可选:

          • QProcess::SeparateChannels:stdout 和 stderr 分开(默认)。

          • QProcess::MergedChannels:stdout 和 stderr 合并为一个输出流。

          • QProcess::ForwardedChannels:将输出转发到父进程的 stdout/stderr。

          • QProcess::DisabledChannels(已废弃):禁用输出(不推荐)。

      • setEnvironment() vs setProcessEnvironment()

        方法

        输入类型

        默认环境变量

        操作方式

        setEnvironment()

        QStringList

        完全覆盖

        直接指定全部

        setProcessEnvironment()

        QProcessEnvironment

        可继承系统环境

        增删改查

      • 环境设置/通道模式

        • setWorkingDirectory() 指定运行目录,影响路径解析。

        • setEnvironment() 完全定义环境变量,适合自定义环境。

        • setProcessEnvironment() 灵活调整环境变量,基于系统环境。

        • setProcessChannelMode() 控制 stdout 和 stderr 的处理方式,适应不同输出需求。​​

  • 主要信号

    QProcess 的信号机制是其异步操作的核心,允许开发者通过事件驱动的方式监控进程的状态变化和数据输出。这些信号与 Qt 的信号槽机制紧密集成,提供实时反馈。
    • started() 信号在外部进程成功启动时发出,异步性:适合实时监控进程开始。

    • finished(int exitCode, QProcess::ExitStatus exitStatus)

      • 信号在外部进程结束时发出,提供退出代码和退出状态。

      • exitCode:进程返回的退出代码(0 通常表示成功)。

      • exitStatus:退出状态(NormalExit 或 CrashExit)。

    • readyReadStandardOutput()

      • 信号在外部进程的标准输出(stdout)有新数据可读时发出。

      • 实时性:数据可用时立即触发,支持动态读取。

      • 无参数:需手动读取(如 readAllStandardOutput())。

    • readyReadStandardError()

      • 信号在外部进程的标准错误(stderr)有新数据可读时发出。

      • 错误捕获:专门处理 stderr 数据。

      • 实时响应:与 stdout 独立触发,支持分开处理。

      • 需配合读取:信号本身不含数据,需调用 readAllStandardError()。

    • errorOccurred(QProcess::ProcessError error)

      • ​​​​​​​信号在进程启动或运行时发生错误时发出,提供具体的错误类型,帮助诊断问题。

      • error:错误类型枚举(FailedToStart、Crashed、Timedout 等)。

    • stateChanged(QProcess::ProcessState newState)

      • 信号在进程状态发生变化时发出,提供新的状态值,帮助跟踪进程生命周期。

      • newState:新状态(NotRunning、Starting、Running)。

    • 信号构成了 QProcess 的事件驱动核心

      • 生命周期:started()、finished() 和 stateChanged() 监控进程开始、结束和状态变化。

      • 数据输出:readyReadStandardOutput() 和 readyReadStandardError() 处理 stdout 和 stderr 数据。

      • 异常处理:errorOccurred() 捕获错误。

  • 进程通道模式详解

    进程通道模式由 setProcessChannelMode(QProcess::ProcessChannelMode mode) 设置,控制 QProcess 如何处理外部进程的标准输出(stdout)和标准错误(stderr)。这些模式在进程启动前设置,影响输出数据的流向和读取方式。
    • SeparateChannels

      • SeparateChannels 是默认模式,表示标准输出(stdout)和标准错误(stderr)保持独立,分别通过各自的通道输出。

      • stdout 数据通过 readAllStandardOutput() 或 readyReadStandardOutput() 读取。

      • stderr 数据通过 readAllStandardError() 或 readyReadStandardError() 读取。

      • 两个通道互不干扰,数据不会混合。

    • MergedChannels

      • ​​​​​​​MergedChannels 将标准输出(stdout)和标准错误(stderr)合并为一个输出流,所有数据都通过 stdout 通道输出。

      • stdout 和 stderr 数据都由 readAllStandardOutput() 或 readyReadStandardOutput() 读取。

      • readAllStandardError() 和 readyReadStandardError() 无效(无数据)。

      • 输出顺序可能因进程实现而异(不保证严格按时间顺序)。

    • ForwardedChannels

      • ​​​​​​​ForwardedChannels 将外部进程的 stdout 和 stderr 直接转发到父进程(即调用 QProcess 的程序)的标准输出和标准错误通道,通常显示在控制台上。

      • stdout 和 stderr 数据不会被 QProcess 捕获,而是直接输出到终端。

      • readAllStandardOutput() 和 readAllStandardError() 无数据可读。

      • 类似运行命令时的原始行为。

    • 通道模式(QProcess::ProcessChannelMode)

      模式

      行为

      读取方式

      使用场景

      SeparateChannels

      stdout 和 stderr 分开

      分别读取 stdout 和 stderr

      日志分离、调试

      MergedChannels

      stdout 和 stderr 合并到 stdout

      仅读取 stdout(含全部数据)

      统一输出、简单显示

      ForwardedChannels

      输出转发到父进程终端

      无法读取,直接显示

      调试、直观交互

  • 同步与异步执行

    ​​​​​​​QProcess 提供了两种主要的执行外部进程的方式:异步执行(start())和同步执行(execute())。这两种方式在执行流程、交互能力和适用场景上存在显著差异。
    • 异步执行 (start(const QString &program, const QStringList &arguments, OpenMode mode = ReadWrite))

      • start() 以异步方式启动外部进程,调用后立即返回,进程在后台运行。开发者可以通过信号槽机制监控进程状态和输出,实现实时交互。

      • program:要运行的程序路径或命令。

      • arguments:传递给程序的参数列表。

      • mode:输入输出通道的打开模式(默认 ReadWrite)。

      • 非阻塞:调用 start() 后,控制权立即返回给调用线程,进程在后台运行。

      • 实时交互:支持通过 write() 写入 stdin,通过 readAllStandardOutput() 和 readAllStandardError() 读取输出。

      • 信号驱动:依赖信号(如 started()、finished()、readyReadStandardOutput())处理进程事件。

      • 生命周期管理:可以通过 kill() 或 terminate() 手动终止进程。

    • 同步执行 (execute(const QString &program, const QStringList &arguments = QStringList()))

      • ​​​​​​​execute() 以同步方式运行外部进程,调用后线程会被阻塞,直到进程完成并返回退出代码。它是一个静态方法,适合简单的一次性任务。

      • program:要运行的程序路径或命令。

      • arguments:传递给程序的参数列表(可选)。

      • 返回值:进程的退出代码(0 通常表示成功)。

      • 阻塞:调用线程暂停,直到进程结束。

      • 无交互:无法实时读取 stdout/stderr 或写入 stdin。

      • 简单直接:无需信号槽,直接返回退出代码。

      • 一次性:进程运行后自动清理,无需手动管理。

    • 使用说明

      特性

      异步执行 (start())

      同步执行 (execute())

      执行方式

      非阻塞,后台运行

      阻塞,等待完成

      交互性

      支持 stdin/stdout/stderr 交互

      无交互能力

      返回值

      无(通过信号获取结果)

      退出代码

      复杂度

      需要信号槽管理

      简单直接

      适用场景

      GUI、实时输出、复杂任务

      短时任务、非 GUI、简单命令

      资源管理

      需手动控制(如关闭进程)

      自动清理

  • 高级用法

    QProcess 不仅限于基本的进程启动和输出读取,还支持管道操作、通道自定义以及与网络功能的集成。这些高级用法扩展了其在多进程协作和跨系统交互中的应用。
    • 管道重定向

      • ​​​​​​​管道重定向允许将一个进程的输出(stdout)作为另一个进程的输入(stdin),实现多进程之间的数据流传递。

      • 方法:setStandardOutputProcess(QProcess *destination)将当前进程的 stdout 重定向到目标进程的 stdin。

    • 自定义通道模式​​​​​​​

      • setStandardOutputFile(const QString &fileName):将 stdout 重定向到指定文件。

      • setStandardErrorFile(const QString &fileName):将 stderr 重定向到指定文件。

      • setStandardInputFile(const QString &fileName):从指定文件读取 stdin 数据。

      • 文件重定向:输出直接写入文件而非程序缓冲区,输入从文件读取。

      • 独立控制:stdout 和 stderr 可分别重定向到不同文件。

    • 与网络结合

      • ​​​​​​​QProcess 可以与 Qt 的网络模块(如 QTcpSocket、QNetworkAccessManager)结合,通过外部进程处理网络数据,或将进程输出发送到网络。

      • 进程输出到网络:读取进程输出,通过 socket 或 HTTP 发送。

      • 网络数据到进程:从网络接收数据,写入进程 stdin。

      • 数据桥接:QProcess 作为本地处理单元,网络模块负责远程通信。

      • 异步性:结合 QProcess 的信号和网络的事件循环,实现非阻塞操作。

    • 用法说明

      高级用法

      功能描述

      关键方法/技术

      使用场景

      管道重定向

      将一个进程的输出作为另一个进程的输入

      setStandardOutputProcess()

      数据处理链、多阶段任务

      自定义通道模式

      重定向输入输出到文件或设备

      setStandardOutputFile()等

      日志记录、静默执行、批量输入

      与网络结合

      进程与网络数据交互

      QProcess +QTcpSocket

      等网络类

      远程命令、数据处理服务、分布式系统

  • ​错误处理

    QProcess 在运行外部进程时可能会遇到各种错误,例如启动失败、执行异常或超时。Qt 提供了多种机制来检测和处理这些错误,包括信号、状态检查和输出分析。
    • ​​​​​​​​​​​​​​启动错误:启动错误发生在调用 start() 或 startDetached() 时,进程无法成功启动。

      • 方法:调用 error() 返回 QProcess::FailedToStart,通过 errorString() 获取详细描述。

      • 信号:errorOccurred(QProcess::FailedToStart) 信号触发。

    • 执行错误

      ​​​​​​​执行错误发生在进程启动后运行时出现问题,进程崩溃(Crash)或因非法操作终止。
      • 信号:errorOccurred(QProcess::Crashed) 信号触发。

      • 方法:exitStatus() 返回 QProcess::CrashExit,error() 返回 QProcess::Crashed。

      • 使用 readAllStandardError() 获取可能的错误信息。

    • 超时错误

      • 超时错误发生在等待进程事件(如启动、数据可读或结束)时超过指定时间。

      • 方法:waitForStarted()、waitForFinished() 等返回 false,error() 返回 QProcess::Timedout。

      • 信号:errorOccurred(QProcess::Timedout) 信号触发。

    • 处理 errorOccurred() 信号

      • ​​​​​​​涵盖所有错误类型(启动、执行、超时等)。

      • 全面性:捕获所有可能的错误类型。

      • 实时性:错误发生时立即触发。

      • 补充信息:结合 errorString() 获取详细描述。

    • 检查退出代码和标准错误输出

      • 退出代码(exitCode())和标准错误输出(stderr)是判断进程执行结果的重要依据。

      • 退出代码:通过 finished() 信号或 exitCode() 获取。

      • 标准错误:通过 readyReadStandardError() 信号或 readAllStandardError() 读取。

    • 错误类型分类处理

      错误类型

      检测方法

      常见原因

      处理建议

      启动错误

      errorOccurred(QProcess::FailedToStart)

      文件不存在、权限不足

      检查路径和权限,记录错误

      执行错误

      errorOccurred(QProcess::Crashed)

      进程崩溃、环境配置错误

      检查参数和 stderr,调试崩溃原因

      超时错误

      waitFor*()返回false,QProcess::Timedout

      进程卡死、执行时间过长

      调整超时时间,必要时终止进程

      信号处理

      errorOccurred(QProcess::ProcessError)

      各种错误

      根据错误类型分类处理,记录日志

      退出码/stderr

      exitCode()、readAllStandardError()

      进程逻辑错误、外部依赖缺失

      分析退出码和 stderr,提示用户

测试代码

案例编号

主题

难度

涉及内容

适用场景

1

基础使用

简单

启动、同步/异步、输出读取

初学、简单命令执行

2

交互式命令

中等

交互、信号、通道模式

动态输入输出、实时反馈

3

错误与状态监控

中等

信息获取、控制、错误处理、信号

健壮性任务、构建系统

4

管道与通道自定义

较难

管道、通道模式、高级用法

数据处理链、文件操作

5

与网络结合

复杂

异步、网络集成、高级用法

远程服务、分布式系统

案例 1:基础使用 - 运行简单命令并获取输出

运行一个简单的系统命令(如 dir 或 ls),获取其输出并显示。

#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
#include <QtGlobal>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv); // 添加事件循环支持扩展性

    QProcess process;

    // ======================
    // 同步方式执行命令
    // ======================
    QString command;
    QStringList arguments;
    if (QSysInfo::productType() == "windows") {
        command = "cmd.exe";
        arguments << "/c" << "dir"; // 使用 cmd.exe 执行 dir
    } else {
        command = "ls";
//        arguments << "-l"; // 示例参数,可选
    }

    int exitCode = QProcess::execute(command, arguments);
    if (exitCode == 0) {
        qDebug() << "Command executed successfully";
    } else {
        qDebug() << "Command failed with exit code:" << exitCode;
    }

    // ======================
    // 异步方式获取输出
    // ======================
    process.start(command, arguments);
    if (!process.waitForStarted()) {
        qDebug() << "Failed to start:" << process.errorString();
        return 1;
    }

    process.waitForFinished();
    QString output = QString::fromLocal8Bit(process.readAllStandardOutput()); // 处理 Windows 本地编码
    qDebug() << "Output:" << output.trimmed();

    return app.exec();
}
// ======================
// console
// ======================
//Makefile
//QtCore
//main.moc
//main.o
//moc_EventObject.cpp
//moc_EventObject.o
//moc_SenderReceiver.cpp
//moc_SenderReceiver.o
//moc_predefs.h
//Command executed successfully
//Output: "Makefile\nQtCore\nmain.moc\nmain.o\nmoc_EventObject.cpp\nmoc_EventObject.o\nmoc_SenderReceiver.cpp\nmoc_SenderReceiver.o\nmoc_predefs.h"
案例 2:交互式命令 - 实时读取和输入

运行一个交互式命令行工具(如计算器 bc),实时读取输出并发送输入。

#include <QProcess>
#include <QDebug>
#include <QCoreApplication>

// ======================
// 主函数
// ======================
int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv); // 添加事件循环支持异步信号

    QProcess process;

    // 设置通道模式为分开(默认)
    process.setProcessChannelMode(QProcess::SeparateChannels);

    // ======================
    // 连接信号以实时读取输出
    // ======================
    QObject::connect(&process, &QProcess::readyReadStandardOutput, [&process]() {
        qDebug() << "Result:" << process.readAllStandardOutput();
    });

    // ======================
    // 根据操作系统选择合适的交互式进程
    // ======================
#ifdef Q_OS_WIN
    // Windows 使用 powershell.exe 执行计算
       process.start("powershell.exe", QStringList() << "-NoProfile" << "-NoLogo" << "-Command" << "(2 + 3)");
#else
    // Unix/Linux 使用 bc
    process.start("bc");
    process.waitForStarted();

    // 发送计算指令
    process.write("2 + 3\n"); // 输入表达式
    process.write("quit\n");  // 退出 bc
#endif

    process.waitForFinished();

    return app.exec(); // 使用事件循环确保信号被处理
}


// ======================
// console
// ======================
//Result: "5\n"  linux
//Result: "5\r\n" windows


案例 3:错误处理与状态监控 - 编译代码并分析结果

运行编译器(如 gcc),处理启动错误、执行错误,并检查退出代码和 stderr 输出。

#include <QProcess>
#include <QDebug>
#include <QObject>

// ======================
// 主函数
// ======================
int main(int argc, char *argv[]) {
    Q_UNUSED(argc);
    Q_UNUSED(argv);

    QProcess process;

    // ======================
    // 设置工作目录
    // ======================
    process.setWorkingDirectory("/path/to/project");

    // ======================
    // 错误处理信号
    // ======================
    QObject::connect(&process, &QProcess::errorOccurred, [&process](QProcess::ProcessError error) {
        qDebug() << "Error:" << process.errorString();
        switch (error) {
            case QProcess::FailedToStart:
                qDebug() << "Failed to start";
                break;
            case QProcess::Crashed:
                qDebug() << "Process crashed";
                break;
            default:
                break;
        }
    });

    // ======================
    // 状态变化监控
    // ======================
    QObject::connect(&process, &QProcess::stateChanged, [](QProcess::ProcessState state) {
        qDebug() << "State:" << (state == QProcess::NotRunning ? "Not Running" :
                                 state == QProcess::Starting ? "Starting" : "Running");
    });

    // ======================
    // 进程完成信号
    // ======================
    QObject::connect(&process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),[&process](int exitCode, QProcess::ExitStatus status) {
        qDebug() << "Exit code:" << exitCode << "Status:" << (status == QProcess::NormalExit ? "Normal" : "Crashed");
        if (exitCode != 0) {
            qDebug() << "Errors:" << process.readAllStandardError();
        }
    });

    // ======================
    // 启动进程
    // ======================
    process.start("gcc", QStringList() << "nonexistent.c"); // 故意编译不存在的文件
    process.waitForFinished();

    return 0;
}

// ======================
// console
// ======================
//State: Starting
//State: Not Running
//Error: "chdir: No such file or directory"
//Failed to start
案例 4:管道与通道自定义 - 多进程协作

使用管道将 ls 的输出传递给 sort 排序,并将结果重定向到文件。

#include <QProcess>
#include <QDebug>
#include <QFile>

int main(int argc, char *argv[]) {
    QProcess process1; // 源进程
    QProcess process2; // 目标进程

    // 设置管道:process1 的 stdout 到 process2 的 stdin
    process1.setStandardOutputProcess(&process2);

    // 设置通道模式和输出重定向
    process2.setProcessChannelMode(QProcess::MergedChannels); // 合并 stdout 和 stderr
    process2.setStandardOutputFile("sorted_output.txt");      // 输出到文件

    // 启动进程
    process1.start("ls", QStringList() << "-l");
    process2.start("sort");//对内容进行排序

    // 等待完成
    process1.waitForFinished();
    process2.waitForFinished();

    // 读取文件内容
    QFile file("sorted_output.txt");
    if (file.open(QIODevice::ReadOnly)) {
        qDebug() << "Sorted output:" << file.readAll();
        file.close();
    }

    return 0;
}

// ======================
// console sorted_output.txt
// ======================
//-rw-r--r-- 1 user user      0 Apr  8 18:16 sorted_output.txt
//-rw-r--r-- 1 user user   4511 Mar 31 21:07 moc_EventObject.cpp
//-rw-r--r-- 1 user user   6851 Mar 31 20:10 moc_SenderReceiver.cpp
//-rw-r--r-- 1 user user   7428 Apr  4 00:02 main.moc
//-rw-r--r-- 1 user user  14725 Mar 31 20:09 moc_predefs.h
//-rw-r--r-- 1 user user  22585 Apr  8 18:16 Makefile
//-rw-r--r-- 1 user user 593248 Apr  8 18:14 main.o
//-rw-r--r-- 1 user user 611312 Mar 31 21:07 moc_EventObject.o
//-rw-r--r-- 1 user user 631336 Mar 31 20:10 moc_SenderReceiver.o
//-rwxr-xr-x 1 user user 371704 Apr  8 18:14 QtCore
//total 2228
案例 5:与网络结合 - 远程命令执行服务

构建一个简单的 TCP 服务器,接收客户端命令,通过 QProcess 执行并返回结果。

服务器端:.pro添加:QT += network

#include <QCoreApplication>
#include <QProcess>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>

// ======================
// 主函数
// ======================
int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QTcpServer server;

    // ======================
    // 检查服务器是否启动
    // ======================
    if (!server.listen(QHostAddress::Any, 12345)) {
        qDebug() << "Server failed to start:" << server.errorString();
        return 1;
    }
    qDebug() << "Server running on port 12345";

    // ======================
    // 处理新连接
    // ======================
    QObject::connect(&server, &QTcpServer::newConnection, [&server]() {
        QTcpSocket *client = server.nextPendingConnection();
        if (!client) {
            qDebug() << "Null client pointer";
            return;
        }

        // ======================
        // 为每个客户端创建独立的 QProcess 对象
        // ======================
        QProcess *process = new QProcess(client); // 绑定到 client 的生命周期
        process->setProcessChannelMode(QProcess::SeparateChannels);

        // ======================
        // 客户端数据到达时执行命令
        // ======================
        QObject::connect(client, &QTcpSocket::readyRead, [client, process]() {
            QByteArray commandData = client->readAll();
            QString command = QString::fromUtf8(commandData).trimmed();
            if (command.isEmpty()) {
                qDebug() << "Empty command received";
                client->write("Error: No command provided\n");
                return;
            }

            // 解析命令和参数
            QStringList parts = command.split(" ", Qt::SkipEmptyParts);
            QString program = parts.takeFirst();
            QStringList arguments = parts;

            // 启动进程
            process->start(program, arguments);
            if (!process->waitForStarted(1000)) {
                qDebug() << "Process failed to start:" << process->errorString();
                client->write("Error: Failed to start process\n");
                return;
            }
        });

        // ======================
        // 发送进程输出到客户端
        // ======================
        QObject::connect(process, &QProcess::readyReadStandardOutput, [client, process]() {
            QByteArray output = process->readAllStandardOutput();
            if (client->state() == QAbstractSocket::ConnectedState) {
                client->write(output);
            }
        });

        // ======================
        // 发送错误输出
        // ======================
        QObject::connect(process, &QProcess::readyReadStandardError, [client, process]() {
            QByteArray error = process->readAllStandardError();
            if (client->state() == QAbstractSocket::ConnectedState) {
                client->write("Error: " + error);
            }
        });

        // ======================
        // 进程结束时通知客户端
        // ======================
        QObject::connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), [client, process](int exitCode, QProcess::ExitStatus status) {
            if (client->state() == QAbstractSocket::ConnectedState) {
                client->write(QByteArray("Exit code: ") + QByteArray::number(exitCode) + "\n");
                client->disconnectFromHost();
            }
        });

        // ======================
        // 客户端断开时清理
        // ======================
        QObject::connect(client, &QTcpSocket::disconnected, [client, process]() {
            qDebug() << "Client disconnected";
            process->deleteLater(); // 清理 process
            client->deleteLater();  // 清理 client
        });
    });

    return app.exec();
}
// ======================
// console
// ======================
//Server running on port 12345
//Client disconnected

客户端:.pro添加:QT += network

#include <QCoreApplication>
#include <QTcpSocket>
#include <QDebug>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    QTcpSocket socket;
    socket.connectToHost("localhost", 12345);
    if (socket.waitForConnected(3000)) {
        socket.write("ls -l\n"); // Linux 示例命令
        socket.waitForReadyRead(5000);
        qDebug() << "Response:" << socket.readAll();
        socket.disconnectFromHost();
    } else {
        qDebug() << "Connection failed:" << socket.errorString();
    }

    return app.exec();
}
// ======================
// console
// ======================
//Response: "..."

QSharedMemory

  • :​接下来,学习QSharedMemory类,它允许多个进程共享同一块内存区域,实现高效的数据交换。掌握如何创建、附加和分离共享内存段,以及处理同步和并发问题。 ​

QSystemSemaphore

  • :​然后,学习QSystemSemaphore类,它提供系统级的信号量,用于控制对共享资源的访问,确保多个进程之间的同步。了解如何使用信号量来避免竞争条件和死锁。 ​

QLocalServer 和 QLocalSocket

  • :​之后,学习QLocalServerQLocalSocket类,它们用于在同一台机器上的不同进程之间通过本地套接字进行通信。掌握如何创建本地服务器、监听连接,以及在客户端和服务器之间传递数据。


QSharedMemory 提供了进程间共享内存的访问,允许多个进程共享同一块内存区域。

七. 插件支持 (Plugin Support)

  • QPluginLoader
    QPluginLoader 用于加载动态插件,使得应用程序能够在运行时加载和卸载插件。

  • QFactoryInterface
    QFactoryInterface 是插件接口,插件可以实现特定功能,并通过该接口供应用程序使用。

八. 文本编解码 (Text Codecs)

  • QTextCodec
    QTextCodec 用于文本编码和解码,支持多种字符集,如 UTF-8、GBK、ISO-8859-1 等。

九. 动态库加载 (Dynamic Library Loading)

  • QLibrary
    QLibrary 用于加载动态链接库,并提供访问其导出函数的能力,支持跨平台的动态库管理。

十. 全局函数

  • qAbs

        计算绝对值。

  • qDebug、qWarning、qCritical

        调试和日志输出。

  • qInstallMsgHandler

        安装消息处理程序。

  • qVersion

返回 Qt 版本。

  • qRegisterResourceData 和 qUnregisterResourceData:

资源数据管理。

十一. 其他实用工具

  • QUrl

URL 解析和生成。

  • QRandomGenerator

线程安全的随机数生成。

  • QCryptographicHas

加密哈希类(如 MD5、SHA-256)。

  • QJsonDocument、QJsonArray、QJsonObject、QJsonValue

JSON 处理:

  • QRegularExpression

Perl 兼容的正则表达式。

  • QSettings

跨平台应用设置存储。

  • QStandardPaths

返回标准目录路径。

  • QDebug

调试输出工具。

  • QCalendar

支持多种日历系统。

  • QDeadlineTimer

截止时间管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旭唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
OSZAR »