背景
最近在做一個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有兩個可能原因:
- 多個資源使用了相同的key值
- 資源文件找不到
結合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. 找一臺機器進行測試
測試通過,方法可行。
存在問題
- Devexpress程序集的體積偏大,在本例中,實現業務邏輯的程序只有不到1M,而DevExpress程序集有144M,雖然其中有大概60M的Theme程序程序集可以不打包進去,但這體積也還是太大了;
- 要不要在卸載過程中把GAC清理掉是一個問題,因爲對於客戶機而言,把DevExpress留在GAC中並沒有必要,但如果刪掉,萬一用戶有其他程序也引用了Devpexress,就會導致誤刪。