Linux Qt程式設計——在程式中啟動其他應用、指令碼
阿新 • • 發佈:2019-01-23
我們在程式設計過程中,經常會遇到這樣的需求,點選一下按鈕,啟動另外一個應用程式,或者執行一個指令碼。你一定覺得這個多簡單啊,有什麼可寫的?其實實現同一個功能,不同的開發人員寫出的程式碼可能千差萬別,執行效率,容錯率,是否有唯一啟動保護等……當然,我們還是需要通過衡量具體的需求和環境來設計自己的程式碼,量體裁衣。
最簡單的,我們可以通過system直接啟動一個應用程式或者指令碼:
system("./helloworld");
system("./hello.sh");
操作簡單,但是我們可以很清晰的看到弊端:雖然很順利的匹出一個程序去執行另外一個應用,但是我們拿不到這個新程序的任何東西,也就失去了對這個程序的控制權。所以我們可以嘗試利用QProcess:
void Widget::startApps(QString str)
{
QProcess *proc = new QProcess();
proc->start(str);
}
拿到proc指標,我們可以做一些我們想做的事情。做嵌入式應用程式設計的朋友可能時常會受到環境變數的困擾,很納悶為什麼總是找不到這庫那庫。所以我們可以再完善一下:
void Widget::startApps(QString str) { QProcess *proc = new QProcess(); proc->setEnvironment(proc->environment()); proc->start(str); proc->waitForStarted(); }
如果我們想要執行的指令碼需要傳參呢?我們有必要完善一下引數列表:
void Widget::startSh(QString str)
{
QString program = "./hello.sh";
QStringList arguments;
arguments << str;
QProcess *myProcess = new QProcess();
myProcess->start(program, arguments);
}
專案中,我們經常遇到這樣的情況:模組一單獨工作正常,模組二單獨工作也正常,但是整合到一起,在特定的環境下就出這樣那樣的問題。舉一個啟動應用程式的例子:程序間通訊很容易出錯,程序A傳送啟動helloworld的訊息給程序B,程序B接到訊息就啟動helloworld。程序A只發送一次訊息,但是程序B卻接到2個傳送任務,連續啟動2個helloworld,這種錯誤很致命,尤其是在記憶體緊張的環境下,但是的確不容易排查。所以,為了避免悲劇的發生,哪怕我們不能準確的定位程序間通訊的錯誤根源,聰明的程式設計師依舊可以解決這個問題:system("ps | grep helloworld |grep -v grep || ./helloworld &");
如果你還不熟悉指令碼語言,那麼我很樂意解釋一下:ps檢視系統程序資訊,grep檢索一下helloworld相關的程序,然後排除掉grep本身這個程序,如果已經存在一個helloworld,那麼不進去執行,如果沒有存在helloworld,就啟動一個helloworld。即完成了單一啟動保護處理。
如果你需要必須保證啟動一個新的helloworld,那麼依舊有好辦法,先殺掉可能存在的helloworld,然後再啟動,無聲無息:
system("killall helloworld");
如果不確定應用名字就是helloworld,我們只需要把命令替換成:ps aux | grep helloworld | grep -v grep |awk '{print $2}' | xargs kill 2&> /dev/null
需要提醒的是,根據ps的輸出,找到pid那一列,如果在第一列,則改成print $1 ,Busybox可能會存在差異所以要注意。
待續……