
QProcess是用来启动和管理外部进程的
一、基础使用
1.启动进程的三种方式
cpp
//1.start方式
QProcess process;
process.start("program",{"arg1","arg2"});
//或者
QProcess process1;
process1.setProgram("program");
process1.setArguments({"arg1","arg2"});
process1.start();
//2.分离启动(独立进程)
qint64 pid;
QProcess::startDetached("command", arguments, workingDir, &pid);
//3.静态函数方式(同步执行)
int exitCode = QProcess::execute("command", arguments);
QByteArray output = QProcess::systemEnvironment();

2.重要的信号和槽
cpp
QProcess process2;
//进程启动
connect(&process2,&QProcess::started,[](){
qDebug()<<"QProcess::started";
});
//进程结束
using FinishedSignal = void (QProcess::*)(int, QProcess::ExitStatus);
FinishedSignal finishedSignal = &QProcess::finished;
connect(&process2,finishedSignal,[](int exitCode, QProcess::ExitStatus exitStatus){
if (exitStatus == QProcess::NormalExit) {
qDebug() << "Normal exit";
}
});
// 输出读取信号
connect(&process, &QProcess::readyReadStandardOutput, [&](){
qDebug() << "标准输出:" << process.readAllStandardOutput();
});
connect(&process, &QProcess::readyReadStandardError, [&](){
qDebug() << "标准错误:" << process.readAllStandardError();
});
// 错误处理
connect(&process, &QProcess::errorOccurred, [](QProcess::ProcessError error){
qDebug() << "进程错误:" << error;
});
//数据读取信号
//任意输出就绪,不区分stdout/stderr
connect(&process, &QProcess::readyRead, [&]() {
QByteArray data = process.readAll();
});
//状态变化(NotRunning-》Starting-》Running这几种状态的转变)
connect(&process, &QProcess::stateChanged,
[](QProcess::ProcessState newState) {
qDebug() << "State changed to:" << newState;
});
二、进程控制
1.启动和终止进程
cpp
/**************启动相关***************/
QProcess process;
process.start("program");
// 等待启动(最多等待5秒)
if(!process.waitForStarted(5000)) {
qDebug() << "启动超时";
return;
}
if (process.state() == QProcess::Running) {
// 正在运行
}
/**************终止相关***************/
process.terminate(); // 温和终止(发送终止信号)
process.kill(); // 强制终止(立即结束)
if(!process.waitForFinished(10000)) {//等待结束超时
process.kill(); // 强制终止
}
三、输入输出处理【重点】
1.标准输入输出
cpp
// 写入到进程标准输入
process.write("input data\n");
process.closeWriteChannel(); // 关闭输入通道
// 读取所有输出
connect(&process, &QProcess::readyReadStandardOutput, [&]() {
QString output = QString::fromLocal8Bit(process.readAllStandardOutput());
});
connect(&process, &QProcess::readyReadStandardError, [&]() {
QString error = QString::fromLocal8Bit(process.readAllStandardError());
});
// 逐行读取
while(process.canReadLine()) {
QString line = process.readLine();
}
2.重定向
cpp
// 重定向到文件
process.setStandardOutputFile("output.txt");
process.setStandardErrorFile("error.txt");
process.setStandardInputFile("input.txt");
// 重定向到其他进程
QProcess process1, process2;
process1.setStandardOutputProcess(&process2);
// 重定向到QIODevice
QBuffer buffer;
process.setStandardOutputDevice(&buffer);
四、环境和工作目录
cpp
// 设置工作目录
process.setWorkingDirectory("/path/to/workdir");
// 获取系统环境变量
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
//添加/修改环境变量
env.insert("PATH", "/custom/path:" + env.value("PATH"));
env.insert("MY_VAR", "value");
//应用到进程
process.setProcessEnvironment(env);
五、状态检测
cpp
// 获取进程状态
switch(process.state()) {
case QProcess::NotRunning: break;
case QProcess::Starting: break;
case QProcess::Running: break;
}
// 获取进程ID
qint64 pid = process.processId();
// 检查是否正在运行
if(process.state() == QProcess::Running) {
// 进程正在运行
}
六、错误处理
1.错误类型判断
cpp
QProcess process;
process.start("nonexistent_program");
connect(&process, &QProcess::errorOccurred, [](QProcess::ProcessError error) {
if(process.error() != QProcess::UnknownError) {
switch(process.error()) {
case QProcess::FailedToStart:
qDebug() << "启动失败,可能程序不存在或无权限";
break;
case QProcess::Crashed:
qDebug() << "进程崩溃";
break;
case QProcess::Timedout:
qDebug() << "超时";
break;
case QProcess::WriteError:
case QProcess::ReadError:
qDebug() << "IO错误";
break;
default:
break;
}
}
}
//2.获取详细错误信息
if (process.state() == QProcess::NotRunning) {
qDebug() << "Process error:" << process.errorString();
qDebug() << "Exit code:" << process.exitCode();
qDebug() << "Exit status:" << process.exitStatus();
}
七、常用模式示例
1.执行shell命令
cpp
QString result;
QProcess process;
process.start("bash", {"-c", "ls -la | grep .txt"});
process.waitForFinished();
result = process.readAllStandardOutput();
2.长时间运行的后台进程
cpp
QProcess* process = new QProcess(this);
connect(process, &QProcess::readyReadStandardOutput, this, &MyClass::handleOutput);
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &MyClass::processFinished);
process->start("long_running_program");
3.管道链式操作
cpp
QProcess grep, wc;
grep.setStandardOutputProcess(&wc);
grep.start("grep", {"pattern", "file.txt"});
wc.start("wc", {"-l"});
wc.waitForFinished();
int lineCount = wc.readAllStandardOutput().trimmed().toInt();
八、注意事项
1.跨平台差异
windows需要处理路径分隔符(使用/或者\)
2.资源管理
使用智能指针或者父对象管理内存
QProcess* process = new QProcess(this);
3.死锁避免
避免同时读写造成死锁
使用waitForReadyRead()而不是无线循环
4.超时设置
process.waitForFinished(30000);