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;
}
浙公网安备 33010602011771号