QProcess 执行脚本和命令

在Qt中经常需要使用 QProcess 来启动一个子进程执行一些命令或启动脚本等操作,常用方案如下:

1、 执行程序和对应参数作为 QString cmdStr

对于将执行程序和对应的参数构建成一个QString时,QProcess是自动将进行拆分,将第一个空格前面的内容作为程序名,后面的作为对应参数,容易出问题。一般会将程序名和各个参数用双引号进行包裹。

Code
    // 函数定义,直接执行对应的cmd
    bool StartProcess(const QString& cmd, QString& outMsg, QString& errMsg, const QString& workingDir)
    {
        QProcess process;

        if (!workingDir.isEmpty())
        {
            if (QDir(workingDir).exists())
            {
                process.setWorkingDirectory(workingDir);
            }
            else
            {
                errMsg = QString("Working directory doesn't exist: %1").arg(workingDir);
                return false;
            }
        }

        process.start(cmd);

        if (!process.waitForStarted(3000))
        {
            errMsg = QString("Process start failed, errMsg = %1").arg(process.errorString());
            return false;
        }

        if (!process.waitForFinished(30000))
        {
            errMsg = "Process execution timeout";
            process.kill();
            return false;
        }

        // 设置编码格式,Windows上cmd执行一般是gbk的编码格式
        const QTextCodec* codec = QTextCodec::codecForName("gbk");
        outMsg = codec->toUnicode(process.readAllStandardOutput());
        errMsg = codec->toUnicode(process.readAllStandardError());

        QProcess::ExitStatus exitStatus = process.exitStatus();
        int exitCode = process.exitCode();
        if (exitStatus == QProcess::NormalExit && exitCode == 0)
            return true;
        else
        {
            errMsg += QString(" \nProcess failed, exitCode=%1").arg(exitCode);
            return false;
        }
    }


    // 调用函数
    bool UnzipFile(const QString& unzipTool, const QString& zipFile, const QString& destDir)
    {
        if (!QFile::exists(unzipTool) || !QFile::exists(zipFile) || !QDir(destDir).exists())
            return false;

        // 构建对应的cmd字串,需要用双引号包裹起来,避免参数中有空格等问题。
        QString cmd = QString("\"%1\" -o \"%2\" -d \"%3\"").arg(unzipTool).arg(zipFile).arg(destDir);

        QString workingDir = QFileInfo(unzipTool).absolutePath();

        QString outMsg, errMsg;
        bool extRes = StartProcess(cmd, outMsg, errMsg, workingDir);

        return extRes;
    }

2、程序名称和参数分开

该方案将程序名称和参数分开,以避免出现解析错误,对应的接口定义和调用案例如下:

Code
    // 功能接口
    bool StartProcess(const QString& program, const QStringList& arguments, QString& outputMsg, QString& errMsg, bool isUtf8)
    {
        outputMsg.clear();
        errMsg.clear();

        QProcess process;
        process.start(program, arguments);

        // 默认等待启动时间
        if (!process.waitForStarted())
        {
            errMsg = process.errorString();
            return false;
        }

        // 最多等待30秒
        if (!process.waitForFinished(30000))
        {
            process.kill();
            errMsg = "timeout";
            return false;
        }

        if (isUtf8)
        {
            outputMsg = QString::fromUtf8(process.readAllStandardOutput());
            errMsg += QString::fromUtf8(process.readAllStandardError());
        }
        else
        {
            outputMsg = QString::fromLocal8Bit(process.readAllStandardOutput());
            errMsg += QString::fromLocal8Bit(process.readAllStandardError());
        }

        QProcess::ExitStatus exitStatus = process.exitStatus();
        int exitCode = process.exitCode();

        return process.exitStatus() == QProcess::NormalExit &&
            process.exitCode() == 0;
    }


  // 调用参数构建
  QString program = "ping";
  QStringList args = { "-n", "1", "192.168.0.11"};
  QString outputMsg, errMsg;
  bool res = StartProcess(program, args, outputMsg, errMsg);

3、 执行脚本文件batch

直接执行一些脚本文件,需要显示使用cmd.exe,以避免各种问题

// 脚本中为Windows上的命令时,encode="gbk",脚本中的命令为远程Linux命令时,encode="UTF-8" 以避免出现乱码
    bool StartBatch(const QString& batchPath, QString& out, QString& err, string encode)
    {
        out.clear();
        err.clear();

        if (!QFile::exists(batchPath))
        {
            err = "Batch file not found.";
            return false;
        }

        QProcess process;

        QStringList args;
        args << "/C" << QDir::toNativeSeparators(batchPath);

        process.start("cmd.exe", args);

        // 等待启动(默认30秒)
        if (!process.waitForStarted())
        {
            err = process.errorString();
            return false;
        }

        // 最多等待30秒
        if (!process.waitForFinished(30000))
        {
            process.kill();
            err = "timeout";
            return false;
        }

        const QTextCodec* codec = QTextCodec::codecForName(encode.c_str());
        out = codec->toUnicode(process.readAllStandardOutput());
        err += codec->toUnicode(process.readAllStandardError());

        return process.exitStatus() == QProcess::NormalExit &&
            process.exitCode() == 0;
    }
posted @ 2026-02-12 17:15  Jeffxue  阅读(38)  评论(0)    收藏  举报