1. 程式人生 > >Linux Qt程式設計——在程式中啟動其他應用、指令碼

Linux Qt程式設計——在程式中啟動其他應用、指令碼

       我們在程式設計過程中,經常會遇到這樣的需求,點選一下按鈕,啟動另外一個應用程式,或者執行一個指令碼。你一定覺得這個多簡單啊,有什麼可寫的?其實實現同一個功能,不同的開發人員寫出的程式碼可能千差萬別,執行效率,容錯率,是否有唯一啟動保護等……當然,我們還是需要通過衡量具體的需求和環境來設計自己的程式碼,量體裁衣。

      最簡單的,我們可以通過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可能會存在差異所以要注意。

      待續……