[QT]QProcess的相关使用

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);

相关推荐
她说..7 分钟前
Java 对象相关高频面试题
java·开发语言·spring·java-ee
watson_pillow38 分钟前
c++ 协程的初步理解
开发语言·c++
庞轩px38 分钟前
深入理解 sleep() 与 wait():从基础到监视器队列
java·开发语言·线程··wait·sleep·监视器
故事和你911 小时前
洛谷-算法1-2-排序2
开发语言·数据结构·c++·算法·动态规划·图论
白毛大侠2 小时前
理解 Go 接口:eface 与 iface 的区别及动态性解析
开发语言·网络·golang
李昊哲小课2 小时前
Python办公自动化教程 - 第7章 综合实战案例 - 企业销售管理系统
开发语言·python·数据分析·excel·数据可视化·openpyxl
Hou'2 小时前
从0到1的C语言传奇之路
c语言·开发语言
黎相思2 小时前
音乐播放器
qt
不知名的老吴3 小时前
返回None还是空集合?防御式编程的关键细节
开发语言·python
迈巴赫车主3 小时前
蓝桥杯3500阶乘求和java
java·开发语言·数据结构·职场和发展·蓝桥杯