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

相关推荐
Mr YiRan1 天前
C++面向对象继承与操作符重载
开发语言·c++·算法
普通网友1 天前
Android Jetpack 架构组件最佳实践之“网抑云”APP
android·架构·android jetpack
普通网友1 天前
原创_Android Jetpack Compose 最全上手指南
android·android jetpack
FDoubleman1 天前
Android Jetpack之Compose入门(一)
android·android jetpack
普通网友1 天前
Android Jetpack从入门到精通,干货满满
android·android jetpack
子云心1 天前
Android Jetpack 系列(七)App Startup 启动优化
android·android jetpack·jetpack·initializer·startup·appstartup
嫩嫩的猿1 天前
android jetpack compose Model对象更新变量 UI不更新、不刷新问题
android·ui·android jetpack
普通网友1 天前
Android Jetpack 之 LifeCycle 组件_android 自定义view lifecycle
android·gitee·android jetpack
一只鹿鹿鹿1 天前
智慧水利一体化建设方案
大数据·运维·开发语言·数据库·物联网