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

相关推荐
小小码农Come on2 小时前
QT信号槽机制原理
开发语言·qt
KoiHeng2 小时前
Java的文件知识与IO操作
java·开发语言
-Try hard-2 小时前
完全二叉树、非完全二叉树、哈希表的创建与遍历
开发语言·算法·vim·散列表
霍理迪2 小时前
JS作用域与预解析
开发语言·前端·javascript
Traced back2 小时前
# C# WinForms 数据库清理系统基础知识与避坑指南
开发语言·数据库·c#
煜磊2 小时前
MD5加盐值-注册与登录
java·开发语言
enbug2 小时前
编译安卓内核:以坚果R1、魔趣MK100(Android 10)系统为例
android·linux
茉莉玫瑰花茶2 小时前
C++ 17 详细特性解析(4)
开发语言·c++·算法
rosmis2 小时前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript