QProcess常用三个函数:
QProcess::execute():
以阻塞方式打开外部程序,只有当外部程序执行完后才继续往后执行现程序。其中,外部程序的标准输出、标准错误都是重定向到现程序的标准输出和标准错误。
QProcess::start():
以子进程的方式打开外部程序,外部进程和现进程执行互不干扰,但外部进程的父进程是现进程。
QProcess::startDetached():
以分离方式打开外部程序,外部进程和现进程执行互不干扰,外部进程的父进程是系统的init进程。
其中start()函数为普通成员函数,execute()和startDetached()为静态成员函数
-
process =
new QProcess();
-
-
connect(process,SIGNAL(started()),SLOT(started()));
-
-
connect(process,SIGNAL(finished(
int,QProcess::ExitStatus)),SLOT(finished()));
-
-
connect(process,SIGNAL(stateChanged(QProcess::ProcessState)),SLOT(stateChanged()));
2、主程序:启动process
-
// QStringList list;
-
// list.append("hello_1");
-
// list.append("world_2");
-
// list.append("ok_3");
-
QStringList
list;
-
list<<"hello_1"<<"world_2"<<"ok_3";
-
-
QString program = "E:\\hit-qt\\build-TestCallTo-Desktop_Qt_5_8_0_MinGW_32bit-Debug\\debug\\TestCallTo.exe";
-
-
process->start(program,
list);
3、主程序:注意start和startDetached的区别
process->startDetached(QString("E:\\hit-qt\\build-TestCallTo-Desktop_Qt_5_8_0_MinGW_32bit-Debug\\debug\\TestCallTo.exe"),list);
start是一体式的:外部程序启动后,将随主程序的退出而退出;
startDetached是分离式的:外部程序启动后,不会随主程序的退出而退出。
重要区别:如果是start则回调都可以正常接收到信息;如果是startDetached则回调无法正常接收到信息。
4、主程序:只有在外部程序退出之后才能获取到返回数据
经测试,只有在外部程序返回之后才能获取到不管是main的返回值,还是打印输出数据。
使用标准输出,任何时候都可以获得返回:
std::cout<<"it's from cout"<<std::endl;
5、主程序:获取main返回值
建立连接:
connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),SLOT(finished(int,QProcess::ExitStatus)));
回调:
-
void Widget::finished(
int exitCode,QProcess::ExitStatus exitStatus)
-
{
-
qDebug()<<
"finished";
-
-
qDebug()<<exitCode;
// 被调用程序的main返回的int
-
qDebug()<<exitStatus;
// QProcess::ExitStatus(NormalExit)
-
qDebug() <<
"finished-output-readAll:";
-
qDebug()<<QString::fromLocal8Bit(process->readAll());
-
qDebug()<<
"finished-output-readAllStandardOutput:";
-
qDebug()<<QString::fromLocal8Bit(process->readAllStandardOutput());
-
-
}
6、主程序:获取返回输出流
建立连接:
-
connect(process,SIGNAL(finished(
int,QProcess::ExitStatus)),SLOT(finished(
int,QProcess::ExitStatus)));
-
-
connect(process,SIGNAL(readyRead()),
this,SLOT(readyRead()));
-
-
connect(process,SIGNAL(readyReadStandardOutput()),
this,SLOT(readyReadStandardOutput()));
回调:
-
void Widget::finished(
int exitCode,QProcess::ExitStatus exitStatus)
-
{
-
qDebug()<<
"finished";
-
-
qDebug()<<exitCode;
// 被调用程序的main返回的int
-
qDebug()<<exitStatus;
// QProcess::ExitStatus(NormalExit)
-
qDebug() <<
"finished-output-readAll:";
-
qDebug()<<QString::fromLocal8Bit(process->readAll());
// ""
-
qDebug()<<
"finished-output-readAllStandardOutput:";
-
qDebug()<<QString::fromLocal8Bit(process->readAllStandardOutput());
// ""
-
}
-
void Widget::readyRead()
-
{
-
qDebug()<<
"readyRead-readAll:";
-
qDebug()<<QString::fromLocal8Bit(process->readAll());
// "hello it is ok!"
-
qDebug()<<
"readyRead-readAllStandardOutput:";
-
qDebug()<<QString::fromLocal8Bit(process->readAllStandardOutput());
// ""
-
}
-
void Widget::readyReadStandardOutput()
-
{
-
qDebug()<<
"readyReadStandardOutput-readAll:";
-
qDebug()<<QString::fromLocal8Bit(process->readAll());
// ""
-
qDebug()<<
"readyReadStandardOutput-readAllStandardOutput:";
-
qDebug()<<QString::fromLocal8Bit(process->readAllStandardOutput());
// ""
-
}
经测试发现,只有在readyRead回调下面使用readAll来读取,才可以读取到数据。
4、外部程序:获取main接收参数
-
// 在这里打印参数
-
QString str1 = QString(
"These are the %1 arguments passed to main:").arg(argc);
-
for(
int i=
1;i<argc;i++)
-
{
-
QString strN = QString(
"%1:%2,").arg(i).arg(argv[i]);
-
str1+=strN;
-
}
-
-
w.SetText(str1);
5、外部程序:返回main参数
自定义返回的参数。程序会在a.exec()阻塞并在程序结束后才会执行return。
-
a.exec();
// 会在这里阻塞
-
-
return
101;
6、外部程序:返回数据
一句话即可。
要用这个:
std::cout<<"it's from cout"<<std::endl;
不要用这个:
printf("hello it is ok!");
7、process其他:stateChanged的各种状态
connect(process,SIGNAL(stateChanged(QProcess::ProcessState)),SLOT(stateChanged(QProcess::ProcessState)));
回调:
-
void Widget::stateChanged(QProcess::ProcessState state)
-
{
-
qDebug()<<
"show state:";
-
switch(state)
-
{
-
case QProcess::NotRunning:
-
qDebug()<<
"Not Running";
-
break;
-
case QProcess::Starting:
-
qDebug()<<
"Starting";
-
break;
-
case QProcess::Running:
-
qDebug()<<
"Running";
-
break;
-
default:
-
qDebug()<<
"otherState";
-
break;
-
}
-
}
8、process其他:调用命令行
-
void Widget::testPing()
-
{
-
QStringList arguments;
-
arguments<<
"/c"<<
"ping www.baidu.com";
//
-
-
QProcess process1(this);
-
process1.start(
"cmd.exe",arguments);
-
process1.waitForStarted();
-
process1.waitForFinished();
-
QString strResult = QString::fromLocal8Bit(process1.readAllStandardOutput());
-
-
QMessageBox msgBox(this);
-
msgBox.setText(strResult);
-
msgBox.exec();
-
}
9、判断启动成功或失败
-
process =
new QProcess(parent);
-
-
process->start(
"TestCallTo.exe",
NULL);
-
-
if(!process->waitForStarted())
-
{
-
qDebug()<<
"failure!";
-
}
else
-
{
-
qDebug()<<
"succ!";
-
}
10、用指针还是引用
(1)引用
使用过程中,发现用引用,则会出问题,比如:
-
QProcess processCreatePdf;
-
-
QStringList
list;
-
list<<"-l"<<"chi_sim"<<path<<CommonTools::getPathWithoutSuffix(path)<<"pdf";
-
-
connect(&processCreatePdf,SIGNAL(started()),SLOT(onProPdfStarted()));
-
-
connect(&processCreatePdf,SIGNAL(finished(
int)),SLOT(onProPdfFinished()));
-
-
processCreatePdf.start("tesseract",
list);
这样做会报错:
-
pdf-started.
-
QProcess: Destroyed
while process (
"tesseract")
is still running.
-
pdf-finished.
started和finished是我做的调试输出,中间那一行是报错。
pdf-started. pdf-finished. code ending.
用引用类型,他会自动回收,当start执行完毕之后,程序认为QProcess已经完成使命了,自动回收,但是此时程序正在执行中,这样回收会导致强行退出,出错。
所以,如果用引用类型来做的话,必须加一个等待结束,然后才自动回收:
-
QProcess processCreatePdf;
-
-
QStringList
list;
-
list<<"-l"<<"chi_sim"<<path<<CommonTools::getPathWithoutSuffix(path)<<"pdf";
-
-
connect(&processCreatePdf,SIGNAL(started()),SLOT(onProPdfStarted()));
-
-
connect(&processCreatePdf,SIGNAL(finished(
int)),SLOT(onProPdfFinished()));
-
-
processCreatePdf.start("tesseract",
list);
-
-
processCreatePdf.waitForFinished();
-
-
qDebug()<<"code ending.";
加了最后这句话之后,他就会阻塞在那里直到回收,注意,代码在这里是阻塞的,而且是先收到finish的消息,然后这个代码才往下走:
pdf-started. pdf-finished. code ending.
(2)指针
指针不会自动回收,那么我们可以不用waitForfinished.
回收的时候可以在finish的回调里面设置:
-
processCreatePdf->deleteLater();
-
-
processCreatePdf =
NULL;
11、execute
此函数与start类似,他相当于start+waitForFinished。
此函数处于阻塞状态,与waiForFinished是一样的。