2009年12月1日

[QT] 使用到 plugin , 要散佈程式時注意事項

在 QT 中有些看似簡單的事, 還是需要一些步驟才能順利完成

初學QT, 就幫忙別部門開發程式, 到收尾階段進行補上 icon 圖示, 結果安裝在別台電腦, 發現 icon 都跑不出來, 即使確定這些 icon 都有被當成 resource 包在執行檔裏, 後來查了 QT Reference 才發現 icon 這種圖形格式, 也是屬於一種plugin, 所以當使用 dynamic link QT時, 這些 dll 也要部署過去

在 qt\plugins下就有依目錄當作分類的各式 plugin, 如果僅是 icon, 便屬於 imageformats\qico4.dll, 安裝到主程式同目錄下的 plugins\imageformats\qicon4.dll 就可以了


如果是使用 static link QT, 需要用巨集 Q_IMPORT_PLUGIN 讓 QT 知道在編譯時, 要將這些 plugin link進主程式,


#include < QtPlugin >

Q_IMPORT_PLUGIN(qico)
int main(int argc, char *argv[]) {
.........
}



不過事情有那麼簡單, 就不需要"師程工"啦我的開發環境是 VS2005 + QT VS plugin 來開發 QT application, 至於為什麼用 VS2005, 一切只是習慣問題(看來得改?), 在這個 app 安裝在使用者電腦上之後, 所有圖示依然是出不來, 當下覺得奇怪, 不是都依照文件把該搬的 dll 都搬過去了嗎? 包含 VS2005的 C/C++ runtime library, 然後我再次查詢文件中的 Deploying an Application on Windows 章節, 嘗試了使用 QApplication::addLibraryPath()去設定路徑, 然後用libraryPaths()印出所有 QT搜尋 DLL 的路徑, 圖示還是出不來, 在浪費了1小時之後, 最後沒有用 Shared QT Libary , 還是用 static QT Library.....(難怪 Google Earth也是這樣子用), 這時第一次感覺 QT 有點難搞.然後時間經過了一個月, 在開發另一個 app 之後還是遇到相同問題, 不過這個 app 不能用 static QT library, 因為雖然是免費使用, 但掛上公司的名字,還是要遵守 QT 的licence-使用LGPL的話, 不能用 static QT, 所以時間依舊又浪費了1個小時...只好再求助 Google 大神, 發現了以下的討論串, 還滿精采的

http://lists.trolltech.com/qt-interest/2007-02/thread00449-0.html

裏面提到有人跑去問 QT 人員, 說是如果使用 VS2005 去編譯 QT 及 QT 程式的話, plugin都載入不了, 這是和 QT plugin 去搜尋 VC C/C++ Runtime Library DLL(CRT)有關係, QT plugin用到的 CRT 只會從 local 目錄去找 (windows/system32), 如果找不到就會標示此 plugin 載入失敗, 下次也不會重新當試載入, 而解決辦法是不要將 CRT 放到跟執行檔同目錄的方式去包裝安裝程式, 而是用 CRT的安裝程式 vcredist_x86.exe(可以從網站上下載, 或是在 VS2005目錄$\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\vcredist_x86\

所以情況變成, 你的安裝程式先要執行這個安裝檔, 讓 user 去安裝, 再安裝自己的程式, 這樣子 plugin就會順利載入然後有人問, 他的程式是放在 USB 隨身碟裏的, 而且使用者不一定有權限安裝(也就是綠色軟體啦), 那該怎麼辦?!


後來又有人提到 CRT 放到 某 plugin 目錄下就能解決了, 但這樣子不是每個plugin的目錄都要放那些 dll 嗎?

而且QT plugin dll一定要放在 /plugins類別/ 底下..

就快放棄的時候...
想說如果把 CRT 的 Microsoft.VC80.CRT.manifest copy到 plugin目錄中, 然後把裏面的 file tag
< file name="msvcr80.dll"..

改成相對路徑

< file name="../../msvcr80.dll"

再使用 QApplication::addLibraryPath() 把 plugin 目錄設定好
Yeah! 可以動也, copy一個文字檔總比copy 3個dll好...暫時先這樣子, 會不會有其它故事就不知道了...



在2009/12/13-------果然此法在Windows Vista/7上失效--------哈!
還好這些 DLL 不算大, 不過一想到只不是要在應用程式裏使用到ICON / JPG / GIF就要搞得大費周章, 真的滿鳥的...