天天看點

用Innosetup打包釋出基于Devexpress的WPF應用背景過程中遇到的問題及解決方案進一步完善存在問題

背景

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

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

安裝完Devexpress後,在項目引用管理器中可以看到Devexpress相關的程式集,引用以下幾個程式集後可以合用WPF版本的Grid

用Innosetup打包釋出基于Devexpress的WPF應用背景過程中遇到的問題及解決方案進一步完善存在問題

問題1:找不到程式集

在開發結束後,用InnoSetup對編譯目标的所有檔案進行打包,在開發機中安裝運作沒有問題,但放到未安裝DevExpress的機器上會報

找不到程式集

的異常,檢查了一下安裝目錄檔案,發現

DevExpress.Xpf.Themes.Office2016White.v17.1.dll

不存在

解決方法1

逐個檢查缺少的程式集,并在生成後事件中通過腳本把缺少的dll拷貝到目标檔案夾,但這種方法檢查成本高,不适用于頻繁變更的程式;

解決方法2

利用DevExpress提供的釋出工具把所需的依賴直接釋出到目标檔案夾

用Innosetup打包釋出基于Devexpress的WPF應用背景過程中遇到的問題及解決方案進一步完善存在問題

這種方法不用擔心丢失所需的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,就會導緻誤删。