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()
- Windows相关
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/96468.html