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 | (int exitCode, QProcess::ExitStatus exitStatus) |
void | (QProcess::ProcessState newState) |
它的一些靜態函式:
Static Public Members
int | (const QString & program, const QStringList & arguments)//阻塞式,直到progress退出 |
int |
(const QString & program |
bool | (const QString & program, const QStringList & arguments, const QString & workingDirectory, qint64 * pid = 0) |
bool | (const QString & program, const QStringList & arguments) |
bool | (const QString & program) |
QStringList |
()//一個有用的獲取系統環境變數的函式。使用如: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");