QProcess
用于完成启动外部程序,并与其交互通信。
启动外部程序的两种方式
依赖式
外部程序启动后,将随主程序的退出而退出。
void start(const QString & program,const QStringList &arguments,OpenMode mode = ReadWrite)
分离式:
外部程序启动后,当主程序退出时并不退出,而是继续运行。
void startDetached(const QString & program,const QStringList & arguments,const QString&workingDirectory=QString(),qint64 *pid =0)
启动进程前的预处理
设置启动路径
可以提前设置启动路径,也可以在start方法中进行设置。
void setProgram(const QString & program)
设置启动命令参数
可以提前设置启动命令参数也可以不设置(非必须),也可以在start方法中进行设置。
void setArguments(const QStringList & arguments) • 1
启动的状态
1、外部程序未启动时,状态是NotRunning;
2、外部程序启动时,状态是Starting;
3、外部程序启动之后,状态是Running,并发出started()信号,此时可对QProcess进行RW操作;
4、外部程序退出时,状态是NotRunning,并发出finished()信号。finished()信号会包含退出码和退出状态信息,可通过exitCode()和exitStatus()来获得。
5、外部程序发生错误时,Qprocess会发出一个error()信号,可通过error()来获得其错误类型,通过state()获得当前程序的状态。
更多说明
有更多想了解Qprocess类的信息,可阅读Qt 助手。 下面列出了,所有可调用的方法。
Public Functions
QProcess(QObject *parent = nullptr) virtual ~QProcess() QStringList arguments() const std::function<void ()> childProcessModifier() const void closeReadChannel(QProcess::ProcessChannel channel) void closeWriteChannel() QProcess::CreateProcessArgumentModifier createProcessArgumentsModifier() const QProcess::ProcessError error() const int exitCode() const QProcess::ExitStatus exitStatus() const QProcess::InputChannelMode inputChannelMode() const QString nativeArguments() const QProcess::ProcessChannelMode processChannelMode() const QProcessEnvironment processEnvironment() const qint64 processId() const QString program() const QByteArray readAllStandardError() QByteArray readAllStandardOutput() QProcess::ProcessChannel readChannel() const void setArguments(const QStringList &arguments) void setChildProcessModifier(const std::function<void ()> &modifier) void setCreateProcessArgumentsModifier(QProcess::CreateProcessArgumentModifier modifier) void setInputChannelMode(QProcess::InputChannelMode mode) void setNativeArguments(const QString &arguments) void setProcessChannelMode(QProcess::ProcessChannelMode mode) void setProcessEnvironment(const QProcessEnvironment &environment) void setProgram(const QString &program) void setReadChannel(QProcess::ProcessChannel channel) void setStandardErrorFile(const QString &fileName, QIODeviceBase::OpenMode mode = Truncate) void setStandardInputFile(const QString &fileName) void setStandardOutputFile(const QString &fileName, QIODeviceBase::OpenMode mode = Truncate) void setStandardOutputProcess(QProcess *destination) void setWorkingDirectory(const QString &dir) void start(const QString &program, const QStringList &arguments = {}, QIODeviceBase::OpenMode mode = ReadWrite) void start(QIODeviceBase::OpenMode mode = ReadWrite) void startCommand(const QString &command, QIODeviceBase::OpenMode mode = ReadWrite) bool startDetached(qint64 *pid = nullptr) QProcess::ProcessState state() const bool waitForFinished(int msecs = 30000) bool waitForStarted(int msecs = 30000) QString workingDirectory() const
Signals
void errorOccurred(QProcess::ProcessError error) void finished(int exitCode, QProcess::ExitStatus exitStatus = NormalExit) void readyReadStandardError() void readyReadStandardOutput() void started() void stateChanged(QProcess::ProcessState newState)
设计一个拉起进程的程序
基本设计思路
1、点击【选择应用】按钮,即可打开文件资源管理器。选择需要拉起的应用,即可在后面的label中显示绝对路径。然后在【添加命令行参数】区域下方添加已注册好的命令以及期望值(这个命令行参数将会在后面介绍)。
2、然后点击右上区域的【拉起进程】按钮,然后会在【日志输出】区域输出拉起成功与否的日志说明和PID号等。最后可以通过【杀死进程】来结束该进程。
效果图
核心代码
控件对象
【添加命令行参数】区域的控件对象为:textEdit
【日志输出】区域的控件对象为:textEdit_2
【选择应用】按钮的控件对象为:pushButton
【拉起进程】按钮的控件对象为:pushButton_3
【杀死进程】按钮的控件对象为:pushButton_2
header file(头文件)
#include <QFileDialog> #include <QProcess>
member variable(成员变量)
QProcess* m_Process;
【选择应用】按钮的槽函数
void MainWindow::on_pushButton_clicked() { QString fileName = QFileDialog::getOpenFileName(this,"选择应用程序","./","Txt files(*.exe)"); ui->lineEdit->setText(fileName); }
【拉起进程】按钮的槽函数
void MainWindow::on_pushButton_3_clicked() { if(nullptr != m_Process) { m_Process->close(); delete m_Process; m_Process = nullptr; ui->textEdit_2->append(QString("杀死已存在的进程!")); } m_Process = new QProcess(this); QString fileName = ui->lineEdit->text(); QStringList args = ui->textEdit->toPlainText().split("\n"); m_Process->start(fileName, args); if(m_Process->waitForStarted(3000)) { qint64 PID =m_Process->processId(); ui->textEdit_2->append(QString("进程拉起成功!PID = %1").arg(PID)); } else { ui->textEdit_2->append(QString("error:进程拉起失败!")); } }
【杀死进程】按钮的槽函数
void MainWindow::on_pushButton_2_clicked() { if(nullptr != m_Process) { m_Process->close(); ui->textEdit_2->append(QString("进程杀死成功!")); } }
UI布局
组织架构
测试效果
Qt解析命令行参数
Qt可以通过QCommandLineParser
和 QCommandLineOption
类可以对命令行进行解析。
命令说明
* 单字符的命令通常以“-” 开头:-h * 多字符的命令通常以“--”开头:--help * 注意 :通常情况下 -abc 会被等同于 -a;-b;-c * 命令后面还可以附带值 例如 -h=45454
增加命令
QCommandLineParser parser; /* *对于有期望值的命令 需要设置Value(setValue) 否则会报错 */ QList<QCommandLineOption> ops; // 带有期望值的open命令 QCommandLineOption op("open"); op.setValueName("string"); // 带有期望值的h命令 QCommandLineOption op2("h"); op2.setValueName("double"); /* * 这里需要添加所有的命令 类似于注册效果 */ ops << op << op2; parser.addOptions(ops); // 处理用户给出的实际命令 parser.process(a);
解析命令
// 解析注册过的命令 if(parser.isSet(op)) { parser.value(op); }
设计一个后台进程的程序
组织架构
核心代码
#include <QCoreApplication> #include <QCommandLineParser> #include <QFile> #include <string> #include <QDebug> #include <iostream> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); /* * 单字符的命令通常以“-” 开头:-h * 多字符的命令通常以“--”开头:--help * * 注意 :通常情况下 -abc 会被等同于 -a;-b;-c */ QCommandLineParser parser; /* *对于有期望值的命令 需要设置Value(setValue) 否则会报错 */ QList<QCommandLineOption> ops; // 带有期望值的open命令 QCommandLineOption op("open"); op.setValueName("string"); // 带有期望值的h命令 QCommandLineOption op2("h"); op2.setValueName("double"); /* * 这里需要添加所有的命令 类似于注册效果 */ ops << op << op2; parser.addOptions(ops); // 处理用户给出的实际命令 parser.process(a); QFile file("e://1.txt"); file.open(QIODevice::Append); if(!file.isOpen()) { exit(EXIT_FAILURE); } // 解析注册过的命令 if(parser.isSet(op)) { std::string log = "open:" + parser.value(op).toStdString() + "\n"; file.write(log.c_str()); std::cout << log;//<< std::endl; } if(parser.isSet(op2)) { std::string log = "h:" + parser.value(op2).toStdString() + "\n"; file.write(log.c_str()); std::cout << log;//<< std::endl; } file.close(); return a.exec(); }
通过Cmd进行测试命令行参数
文件输出
后续
这时其实还不能完整调用,因为部分环境还没有。所以还需要对这个程序进行打包发布。后续将会介绍Qt自带的打包工具。本文内容太多了,就下一篇文中介绍吧。