用Innosetup打包發佈基於Devexpress的WPF應用

背景

最近在做一個Revit插件,需要做一個樹形列表,找了一圈後發現沒有比Devexpress更好用的控件,於是選用Devexpress的grid。

過程中遇到的問題及解決方案

安裝完Devexpress後,在項目引用管理器中可以看到Devexpress相關的程序集,引用以下幾個程序集後可以合用WPF版本的Grid
在這裏插入圖片描述

問題1:找不到程序集

在開發結束後,用InnoSetup對編譯目標的所有文件進行打包,在開發機中安裝運行沒有問題,但放到未安裝DevExpress的機器上會報找不到程序集的異常,檢查了一下安裝目錄文件,發現DevExpress.Xpf.Themes.Office2016White.v17.1.dll不存在

解決方法1

逐個檢查缺少的程序集,並在生成後事件中通過腳本把缺少的dll拷貝到目標文件夾,但這種方法檢查成本高,不適用於頻繁變更的程序;

解決方法2

利用DevExpress提供的發佈工具把所需的依賴直接發佈到目標文件夾
在這裏插入圖片描述
這種方法不用擔心丟失所需的dll,但該工具只提供了可視化版本,無法通過腳本集成到項目中。

解決方法3

把所需的依賴項通過引用管理器添加到項目引用中,並讓它複製到本地,這種方法與方法一類似。

問題2:未實現該方法或操作異常

先看一下異常信息

System.Windows.Markup.XamlParseException: 
“設置屬性“System.Windows.Controls.ContentControl.Content”時引發了異常。”,行號爲“22”,行位置爲“6”。 
---> System.Xaml.XamlObjectWriterException:
 設置屬性“DevExpress.Xpf.Utils.Themes.ResourceDictionaryEx.Source”時引發了異常。
---> System.Windows.Markup.XamlParseException:
 設置屬性“System.Windows.ResourceDictionary.DeferrableContent”時引發了異常。
 ---> System.NotImplementedException: 未實現該方法或操作。

找了一下StackOverflow,並沒有具體針對這這個異常提出的解決方法,得到的信息是,出現XamlParseException有兩個可能原因:

  1. 多個資源使用了相同的key值
  2. 資源文件找不到

結合NotImplementedException,基本可以推斷是Devexpress繼承並實現了WPF框架內的一些抽象類,並重寫了System.Windows.ResourceDictionary.DeferrableContent屬性,但當前程序無法加載該具體類,因此只能報個NotImplementedException了。

解決方法

既然問題極大可能是無法加載程序集,那解決方案就明顯了,讓它能找到唄。而讓它找到最簡單粗暴的方法就是把需要的程序集加入到GAC了。
把程序加入GAC只需要用到以下命令

gacutil /i [assembly].dll

測試機上嘗試了一下,手動把DevExpress的dll都註冊到GAC中,程序可以正常運行,驗證了該方法可行。

進一步完善

既然以上兩步可以解決DevExpress WPF構件的發佈問題,那麼接下來要做的就是把GAC註冊過程加入到安裝步驟中了。

1. 批量註冊GAC腳本

由於客戶機器上可能不存在gacutl.exe,因此首先我們要找到gacutil.exe,並把它打包一起發佈給客戶,gacutil.exe(注意,gacutil.exe.config也需要一起打包)位於路徑C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools中,不同版本的vs對應的版本號可能不一樣。
使用以下腳本把DevExpress dll註冊到GAC

for /f "delims=" %%a in ('dir /b/a-d/oN Dev*.dll') do "%~dp0gacutil" /u "%%~na"

2. 把註冊過程寫入InnoSetup腳本中

[Files]
Source: "./gacutil.exe"; DestDir: "{app}";
Source: "./gacutil.exe.config"; DestDir: "{app}";這裏把gacutil加到安裝包內

;Run節點會在安裝結束後執行,這裏使用後臺進程的方式執行上面的批處理腳本
[run] 
Filename: "{app}\GacReg.bat"; Description: "Install.bat"; Flags: runhidden skipifdoesntexist
[/run]

3. 找一臺機器進行測試

測試通過,方法可行。

存在問題

  1. Devexpress程序集的體積偏大,在本例中,實現業務邏輯的程序只有不到1M,而DevExpress程序集有144M,雖然其中有大概60M的Theme程序程序集可以不打包進去,但這體積也還是太大了;
  2. 要不要在卸載過程中把GAC清理掉是一個問題,因爲對於客戶機而言,把DevExpress留在GAC中並沒有必要,但如果刪掉,萬一用戶有其他程序也引用了Devpexress,就會導致誤刪。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章