Qt模块化笔记之core——QProcess控制外部程序

QProcess是一个为进程间通信创建的类。在linux相关系统中,可以很方便地用它调用执行命令。

它继承自QIODevice.可以想像,它对其它进程的操作方式,就像读写一个文件一样方便。

下面浏览它的公共函数:

	QProcess(QObject * parent = 0)
virtual	~QProcess()

void	setProgram(const QString & program)//设置需要打开的进程
void	setArguments(const QStringList & arguments)//设置参数部分
void	setInputChannelMode(InputChannelMode mode)
void	setReadChannel(ProcessChannel channel)//设置输出通道。下边解释1
void	setNativeArguments(const QString & arguments)
void	setProcessChannelMode(ProcessChannelMode mode)
void	setProcessEnvironment(const QProcessEnvironment & environment)

void	start(const QString & program, const QStringList & arguments, OpenMode mode = ReadWrite)//较常用,直接启动运行某个进程并传入参数
void	start(OpenMode mode = ReadWrite)
void	start(const QString & command, OpenMode mode = ReadWrite)

QByteArray	readAllStandardError()//从输出中得到被操作程序的输出内容。输出时有标准错误输出和标准输出两个管道
QByteArray	readAllStandardOutput()

void	setStandardErrorFile(const QString & fileName, OpenMode mode = Truncate)//与readAllStandardXXX函数相似,只是将程序的输出保存到文件中。设置以下几个后,就read不到相应管道中的内容了。
void	setStandardInputFile(const QString & fileName)
void	setStandardOutputFile(const QString & fileName, OpenMode mode = Truncate)
void	setStandardOutputProcess(QProcess * destination)
void	setWorkingDirectory(const QString & dir)

QProcess::ProcessState	state() const
bool	waitForFinished(int msecs = 30000)
bool	waitForStarted(int msecs = 30000)
QString	workingDirectory() const

QStringList	arguments() const
void	closeReadChannel(ProcessChannel channel)
void	closeWriteChannel()
QProcess::ProcessError	error() const
int	exitCode() const
QProcess::ExitStatus	exitStatus() const
InputChannelMode	inputChannelMode() const
QString	nativeArguments() const
Q_PID	pid() const
ProcessChannelMode	processChannelMode() const
QProcessEnvironment	processEnvironment() const
QString	program() const
ProcessChannel	readChannel() const

1,enum QProcess::ProcessChannel

Constant Value Description
QProcess::StandardOutput默认 0 standard output (stdout) 标准输出
QProcess::StandardError 1 standard error (stderr) 标准错误输出

对于一些继承来的操作函数,如:read(), readAll(), readLine(), 和 getChar(),它们读取时,只能从两个通道中的一个读取得到被操纵程序的标准输出。

可以通过连接信号得到progress的状态:

Signals

void error(QProcess::ProcessError error)
void finished(int exitCode, QProcess::ExitStatus exitStatus)
void readyReadStandardError()
void readyReadStandardOutput()
void started()
void stateChanged(QProcess::ProcessState newState)

它的一些静态函数:

Static Public Members

int execute(const QString & program, const QStringList & arguments)//阻塞式,直到progress退出
int execute(const QString & program)
QString nullDevice()
bool startDetached(const QString & program, const QStringList & arguments, const QString & workingDirectory, qint64 * pid = 0)
bool startDetached(const QString & program, const QStringList & arguments)
bool startDetached(const QString & program)
QStringList systemEnvironment()//一个有用的获取系统环境变量的函数。使用如:QStringList environment = QProcess::systemEnvironment();
// environment = {"PATH=/usr/bin:/usr/local/bin",
// "USER=greg", "HOME=/home/greg"}

————————————————————————————————————————————————————————

下面用mentohust程序举一个它的典型用法:

QString program = "/usr/bin/mentohust";
QStringList arguments;
arguments << "-h";

QProcess *myProcess = new QProcess(parent);
myProcess->start(program, arguments);
mentohust是一个校园网认证的工具,在linux中只有后台,没有UI。使用时可在shell中输入mentohust -h。可以得到帮助信息。上面代码的结果是一样的。

这样启动后,可以用write函数向其写入内容,通过readyReadStandardOutput()等信号连到槽函数,然后用readAllStandardOutput()等读函数读取输出进行处理。


给出一个它的参数的详细链接:https://code.google.com/p/mentohust/wiki/Parameter。可用它试试。或网上有操控MPlayer的,百度下。

————————————————————————————————————————————————————————

接下来看它的更高级用法,以更深理解它:

以下内容来自:http://blog.csdn.net/dbzhang800/article/details/6877762点击打开链接


简单控制台程序

一个程序如何从外界获取信息并向外输出信息呢?

方向

途径

 

获取

命令行参数

int main(int argc, char **argv)

标准输入

scanf()/getc()/getchar()/...

环境变量

getenv()

输出

标准输出

printf() ...

标准出错

fprintf(stderr,...)

返回值

return(x)/exit(X)/_Exit(X)

命令行参数

大多控制台程序都接受命令行参数,一个例子:

#include <stdio.h>
int main(int argc, char **argv)
{
    for (int i=1; i<argc; ++i)
        printf("%s\n", argv[i]);
    return 0;
}

编译,调用程序时可指定命令行,结果:

$ ./process a b "c d"
a
b
c d

用QProcess调用外部程序时,可直接指定命令行参数

QProcess process;
process.start("./process", QStringList()<<"a"<<"b");
process.start("./process a b");

后一种写法看起来写起来比较简洁,但是程序路径或参数中包括空格时,就不如第一种方便了。

注:在Windows平台的某些情况(比如QTBUG7620)下,你可能需要使用

  • QProcess::setNativeArguments()

标准输出

对于控制台程序来说,这个可能是用的最多的了。比如上一个程序,我们遍历命令行参数,然后输到标准输出。

在控制台下,我们通常会使用重定向功能,比如:

$./process a b "c d" > out.txt 

在QProcess下,我们使用

QProcess::readAllStandardOutput ()

获取标准输出

QProcess::setStandardOutputFile()

设置输出到的文件,相当于前面的重定向

QProcess process;
process.start("./process", QStringList()<<"a"<<"b");
process.readAllStandardOutput();

可以使用:

  • QProcess::setStandardOutputProcess()

将标准输出作为另个进程的标准输入。形成 ls -l | more 这样的管道操作

由于QProcess是QIODevice的派生类,故:

  • read()
  • readLine()
  • ...

都可以直接用获取被调用程序的标准输出。

禁止缓冲

注意:如果写的控制台程序准备用于这种途径,且需要实时被读取标准输出,那么一般该程序内需要禁用缓冲

int main()
{
setvbuf(stdout, (char *)NULL, _IONBF, 0);
return 0;
}

因为在控制台运行时,标准输出是行缓的。但是使用管道或重定向以后,一般就是全缓冲。在缓冲区写满或程序退出前,你可能看不到任何输出。

标准出错

相对于标准输出,这个东西大家似乎用的比较少了。

#include <stdio.h>

int main(int argc, char **argv)
{
    fprintf(stdout, "Hello STDOUT!\n");
    fprintf(stderr, "Hello STDERR!\n");
    return 0;
}

编译运行(注意区分两个流,标准出错的文件描述符是2):

$ ./process
Hello STDOUT!
Hello STDERR!
$ ./process > out.txt
Hello STDERR!
$ ./process > out.txt 2>err.txt
$

用QProcess读取标准出错,和前面标准输出是类似的:

  • QProcess::readAllStandardError()
  • QProcess::setStandardErrorFile()

QProcess process;
process.start("./process", QStringList()<<"a"<<"b");
process.readAllStandardOutput();

但是,QProcess作为QIODevice的派生类,read()/readAll()只能读标准输出,不读标准出错,有点说不过去哈。

恩QProcess在这方面足够灵活,你可以通过

  • QProcess::setReadChannel()

进行选择

标准输入

这个也不用多说,使用scanf()/gfets()等函数:

#include <stdio.h>

int main(int argc, char **argv)
{
    char contents[1024];
    fgets(contents, 1024, stdin);
    printf("output: %s", contents);
    return 0;
}

运行:

$ ./process 
1+1=2
output: 1+1=2

如果要输入的内容在文件内,也可以使用重定向

$ ./process < intput.txt
output: contents of input.txt

在QProcess中,直接使用QIODevice的write()函数

QProcess process;
process.start("./process")
process.write("intput");

也可以设置文件作为输入

  • QProcess::setStandardInputFile()

返回值

似乎很多人分不清返回值和标准输出的概念。

int main()
{
return 0;
}

也就是程序中 return X/exit(X) 等函数中指定的值了。

在Windows下,通过

C:\> process.exe
C:\> echo %errorlevel%

在Linux下,通过

$ ./process
$ echo $?

获得返回值。

在QProcess下,则通过:

  • int QProcess::execute()
  • int QProcess::exitCode()

获得返回值。

环境变量

程序运行时可以通过环境变量传递信息:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    char * path = getenv("MYPATH");
    printf("MYPATH= %s\n", path);
    return 1;
}

运行结果(Linux):

$ export MYPATH="/home/dbzhang800"
$ ./process
MYPATH= /home/dbzhang800

Windows下:

C:\> set MYPATH=E:\dbzhang800
C:\> process.exe
MYPATH= E:\dbzhang800

在Qt下,使用 QProcess::setProcessEnvironment() 设置进程的环境变量

QProcess process;
QProcessEnvironment env;
env.insert("MYPATH", "/home/dbzhang800");
process.setProcessEnvironment(env);
process.start("./process");



在 macOS 上,当程序退出时,系统会向它的子进程发送 SIGTERM 信号,使得子进程也随之退出。如果你希望程序退出时不影响 QProcess 的执行,可以通过以下步骤实现: 1. 在程序退出时,不要直接调用 exit() 函数,而是通过捕获 SIGTERM 信号来处理程序退出。 2. 在 QProcess 启动之前,设置 QProcess 的 ProcessChannelMode 为 QProcess::SeparateChannels,这样可以将子进程的标准输出和标准错误输出分别传递到 QProcess 的 readyReadStandardOutput() 和 readyReadStandardError() 信号中。 3. 在收到 SIGTERM 信号时,不要直接调用 QProcess 的 terminate() 函数,而是先向子进程发送 SIGINT 信号,等待一段时间后再调用 QProcess 的 terminate() 函数,确保子进程有足够的时间完成它的任务。 4. 在程序退出前,需要等待 QProcess 执行完成,可以通过调用 QProcess 的 waitForFinished() 函数实现。 以下是示例代码: ```cpp #include <QCoreApplication> #include <QProcess> #include <signal.h> void handleSigTerm(int signum) { // 发送 SIGINT 信号给子进程 QProcess::execute("killall", "-INT", "your_process_name"); // 等待一段时间,确保子进程有足够的时间完成它的任务 QThread::msleep(1000); // 终止子进程 QProcess::execute("killall", "-TERM", "your_process_name"); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 设置信号处理函数 signal(SIGTERM, handleSigTerm); // 创建 QProcess QProcess process; process.setProcessChannelMode(QProcess::SeparateChannels); // 启动子进程 process.start("your_process_name", QStringList() << "arg1" << "arg2"); // 等待子进程执行完成 process.waitForFinished(-1); // 程序退出 return app.exec(); } ``` 其中,your_process_name 为你要执行的子进程的名称。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值