自定義msi安裝包的執行過程
有時候我們需要在程式中執行另一個程式的安裝,這就需要我們去自定義msi安裝包的執行過程。
比如我要做一個安裝管理程式,可以根據使用者的選擇安裝不同的子產品。當使用者選擇了三個產品時,如果分別顯示這三個產品的安裝互動UI顯然是不恰當的。我們期望用一個統一的自定義UI去取代每個產品各自的UI。
平時使用msiexec.exe習慣了,所以最直接的想法就是在一個子程式中執行:
msiexec.exe /qn
這樣固然是能夠完成任務,但是不是太簡陋了? 安裝開始後我們想取消這次安裝怎麼辦? 或者我們還想要拿到一些安裝進度的資訊。
其實可以透過呼叫三個windowsAPI 輕鬆搞定這個事兒!下面的C# demo用一個自定義Form來指示多個MSI檔案的安裝過程。Form上放的是一個捲軸,並且配合一個不斷更新的label。
下面是安裝過程中的UI:
點選Cancel按鈕取消安裝後的UI:
先看一下這三個API:
[DllImport("msi.dll", CharSet = CharSet.Auto)]
internal static extern int (int dwUILevel, IntPtr phWnd);
在呼叫msiexec.exe時,我們透過指定 /q引數讓安裝過程顯示不同的UI。如果不顯示UI的話就要使用引數 /qn 。MsiSetInternalUI方法就是幹這個事兒的。透過下面的呼叫就可以去掉msi中自帶的UI:
NativeMethods.MsiSetInternalUI(2, IntPtr.Zero)
[DllImport("msi.dll", CharSet = CharSet.Auto)]
internal static extern MsiInstallUIHandler ([MarshalAs(UnmanagedType.FunctionPtr)] MsiInstallUIHandlerpuiHandler, NativeMethods.InstallLogMode dwMessageFilter, IntPtr pvContext);
MsiSetExternalUI 函式允許指定一個使用者定義的外部UI handler用來處理安裝過程中產生的訊息。這個外部的UI handler會在內部的UI handler被呼叫前呼叫。 如果在外部的UI handler中返回非0的值,就說明這個訊息已經被處理。
這個外部的UI handler就是MsiSetExternalUI方法的第一個引數,我們透過實現這個handler來處理自己感興趣的訊息, 比如當安裝進度變化後去更新進度條。或者透過它傳遞我們的訊息給msi,比如說告訴msi,停止安裝,執行cancel操作。使用這個方法需要注意的是,當你完成安裝後一定要把原來的handler設回去。否則以後執行msi安裝包可能會出問題。
MSDN上有一個MsiInstallUIHandler 的,感興趣的同學可以看看。
[DllImport("msi.dll", CharSet = CharSet.Auto)]
internal static extern uint ([MarshalAs(UnmanagedType.LPWStr)] string szPackagePath,[MarshalAs(UnmanagedType.LPWStr)] string szCommandLine);
正如其名,這個是真正幹活兒的方法。
實在忍不住要介紹第四個方法,雖然它對實現當前的功能來說是可選的,但對一個產品來說,它卻是用來救命的。
[DllImport("msi.dll", CharSet = CharSet.Auto)]
internal static extern uint (GcMsiUtil.NativeMethods.InstallLogMode dwLogMode,[MarshalAs(UnmanagedType.LPWStr)] string szLogFile, uint dwLogAttributes);
這個方法會把安裝log儲存到你傳遞給它的檔案路徑。有了它生活就會happy很多,很多… 否則當使用者告訴你安裝失敗時,你一定會抓狂的。
好了,下面是MyInstaller demo的主要程式碼:
簡單說明一下,使用者定義的UI執行在主執行緒中,使用BackgroundWorker執行安裝任務。在安裝進行的過程中可以把cancel資訊傳遞給MsiProgressHandler,當MsiProgressHandler檢測到cancel資訊後透過返回值告訴msi的執行引擎,執行cancel操作(msi的安裝過程是相當嚴謹的,可不能簡單的殺掉安裝程式了事!)。
這樣,一個支援cancel的自定義UI的安裝控制程式就OK了(demo哈)。如果要安裝多個msi只需在Install方法中迴圈就可以了。
總結一下,透過呼叫幾個windows API,我們可以實現對msi安裝過程的控制。這比呼叫msiexec.exe更靈活,也為程式日後新增新的功能打下了基礎。
感謝葡萄哥Nick 投稿
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28298702/viewspace-2063238/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 原始碼包安裝過程原始碼
- 自定義效能統計儲存過程包runstats儲存過程
- window安裝msi檔案沒有可執行軟體
- 記錄自定義kafka的parcel庫,CDH安裝kafka服務,無法安裝過去的排雷過程Kafka
- 執行遠端DBMS_LOB包中過程
- MySQL使用之五_自定義函式和自定義過程MySql函式
- 執行一個專案中間報錯裝包過程記錄
- Maven安裝本地的jar包和建立帶模板的自定義專案MavenJAR
- 指令的執行過程
- Hadoop之hive安裝過程以及執行常見問題HadoopHive
- webpack的安裝過程Web
- sql 執行過程SQL
- Redis 命令的執行過程Redis
- HiveSQL的執行過程分析HiveSQL
- jsp的執行過程JS
- ubuntu透過安裝包安裝MongodbUbuntuMongoDB
- 執行緒池建立執行緒的過程執行緒
- KubeKey v3.1 釋出:快速自定義離線安裝包
- APK安裝過程APK
- 安裝wampserver的過程Server
- cocoaPods的安裝過程
- idea中執行maven安裝jar包到本地倉庫跳過testIdeaMavenJAR
- msi檔案怎麼安裝win10_win10系統msi檔案如何安裝Win10
- Linux原始碼包安裝過程及注意事項Linux原始碼
- Android專案實戰 ProgressDialog自定義和封裝過程Android封裝
- MySQL自定義函式與儲存過程MySql函式儲存過程
- 案例展示自定義C函式的實現過程函式
- Android-重新包裝Toast,自定義背景AndroidAST
- Window10 安裝Docker 自定義安裝路徑Docker
- 使用fnm安裝node,並自定義安裝路徑
- Windows如何安裝自定義服務Windows
- javascript引擎執行的過程的理解--執行階段JavaScript
- sql執行過程分析SQL
- Oracle DDL 執行過程Oracle
- Java 程式執行過程Java
- 一條Sql的執行過程SQL
- Javascript中new的執行過程JavaScript
- webpack loader 的執行過程Web