前言
本文旨在優(yōu)化無商業(yè)證書場景下的VSTO分發(fā)方案蜕衡,目標(biāo)是實現(xiàn)用戶端的簡單安裝斟冕、自動更新逃顶。
項目介紹
我花費幾個月時間斷斷續(xù)續(xù)折騰出了一個Excel VSTO托呕,曾在分發(fā)階段遭遇了許多問題。
雖然麻煩不斷券盅,但通過不斷努力(地搜索)帮哈,最終得到了一套比較完善的方案,遂撰文分享一二锰镀。
主要思路:在VSTO的ClickOnce之前套一層安裝器娘侍,進行證書導(dǎo)入等操作,之后自動下載VSTO安裝包泳炉、自動運行憾筏。
- 自制證書
- 給VSTO簽名
- 發(fā)布VSTO
- 自制安裝器
- 安裝器關(guān)鍵方法一:嘗試下載自制證書,并導(dǎo)入用戶機器
- 安裝器關(guān)鍵方法二:若證書導(dǎo)入失敗花鹅,則嘗試寫入注冊表
- 安裝器關(guān)鍵方法三:下載VSTO安裝文件氧腰,運行
- 發(fā)布安裝器
你可以看一下我最終實現(xiàn)的效果:安裝測試
開源地址
由于不是商業(yè)項目,我沒有任何兼容性顧慮刨肃,項目中的.net Framework和Interop.Excel都選擇了最新版本古拴,因此可能會不兼容許多低版本系統(tǒng)或office。
但是真友,不用擔(dān)心黄痪,事實上,即便顧及到兼容性锻狗,我的分發(fā)思路也應(yīng)該是通用的满力。
Excel VSTO部署簡介
直接在Visual Studio中點擊“發(fā)布”,會得到如下結(jié)構(gòu)的文件(微軟官方的圖轻纪,使用了Outlook)油额。
這種發(fā)布方式被稱為“ClickOnce”:Deploy an Office solution by using ClickOnce - Visual Studio?docs.microsoft.com
注:
官網(wǎng)還介紹了以Windows Installer打包發(fā)布VSTO的方式,這種方式不支持自動升級刻帚。
一些第三方打包工具潦嘶,如AdvancedInstaller,我不確定它們能否打包出可自動升級的VSTO崇众。講道理掂僵,它們“應(yīng)該”能做到,畢竟它們是專業(yè)的嘛顷歌。
不與如今的各種應(yīng)用商店作比較锰蓬,這種發(fā)布方式看起來是非常優(yōu)秀的。
你可以指定用戶從你的網(wǎng)站下載setup.exe眯漩,打開后安裝器會自動從你設(shè)定的網(wǎng)絡(luò)路徑拉取所需文件芹扭,
安裝完成之后它能夠保持自動更新……這一切看起來都相當(dāng)完美麻顶,但前提是你得有一個已經(jīng)獲取系統(tǒng)授信的代碼證書。
我也曾嘗試從Comodo申請個人代碼證書舱卡,但是辅肾,經(jīng)過一陣溝通之后,個人代碼證書似乎需要進行Face-to-Face驗證轮锥,而我身在中國……
如果使用自己的測試證書之類的進行ClickOnce發(fā)布矫钓,并妄圖將安裝源設(shè)定在你的網(wǎng)站,甚至還妄想它能夠保持自動更新……那么舍杜,你會得到這個:
當(dāng)然新娜,這張圖是我在網(wǎng)上隨便找的,我自己的分發(fā)問題已經(jīng)徹底解決了蝴簇,所以不會再出現(xiàn)這個界面杯活。
網(wǎng)絡(luò)上的方案
為了兼顧簡易安裝與自動更新匆帚,我翻閱了網(wǎng)絡(luò)上的各種Q&A
熬词,
答案主要分為兩派:“自制證書派”和“改注冊表派”(以下分別簡稱“證書派”與“注冊表派”)。
證書派:自制代碼證書吸重,讓用戶導(dǎo)入你的證書互拾,參見通商軟件MAX的文章
注冊表派:注入注冊表,修改用戶機器的信任提示設(shè)置嚎幸,參見微軟官方文檔
證書派的導(dǎo)入自制證書需要讓用戶多出一步操作颜矿,注冊表派的注入注冊表也需要讓用戶在安裝VSTO之前運行一個事先寫好的腳本。
測試
我的分發(fā)方案
我的思路非常簡單嫉晶,如開頭所述骑疆,
就僅僅是在VSTO的ClickOnce之前加一層安裝器,進行證書導(dǎo)入等操作替废,之后自動下載VSTO安裝包箍铭、自動運行。
-
自制證書
工具任選椎镣,自制一個代碼證書诈火,最終效果差不多是這樣:
自制證書
如果你不知道如何自制證書,那么可以從這里得到幫助状答。
注意冷守,面向公眾的商業(yè)用途切勿使用自制證書,這是對自己和客戶負責(zé)惊科。如果非要使用自制證書拍摇,也請制作一個單獨的代碼簽名證書,萬不可在客戶機器上安裝根證書馆截,因為一旦被有心人曝光充活,你的企業(yè)很可能成為千夫所指。 -
給VSTO簽名
使用自制證書給VSTO簽名 發(fā)布VSTO
雖然你使用了不受用戶信任的自制證書,但你可以假裝它是正規(guī)商業(yè)證書堪唐,直接把你的VSTO發(fā)布到站點上就是了巡语。
到此為止,你已經(jīng)成功獲得了一個用戶無法安裝的VSTO淮菠。它應(yīng)該會有一個類似于“setup.exe”的文件男公,不要讓用戶直接下載它,它應(yīng)該由你的自制安裝器下載到用戶電腦上合陵。-
自制安裝器
它的名字可能會類似于“Installer.exe”枢赔,既可以是命令行腳本也可以是擁有華麗界面的WPF程序,這些都不重要拥知,你可以隨心所欲踏拜。
重要的是,它應(yīng)該是一個單文件軟件低剔,開袋即食的那種單文件軟件速梗,以方便用戶下載、直接點擊運行襟齿。
它的作用主要有以下三點姻锁,我將以代碼說明:-
嘗試下載自制證書,并導(dǎo)入用戶機器
private async Task CertAsync() { string localFullName = $"{DownloadPath}sn.cer"; Uri uri = new Uri("http://Public.mujiannan.me/1Math/sn.cer"); await DownloadAsync(uri, localFullName); using (X509Certificate2 myCert = new X509Certificate2(localFullName)) { using (X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine)) { store.Open(OpenFlags.ReadWrite); store.Remove(myCert); store.Add(myCert); } } }
-
若證書導(dǎo)入失敗猜欺,則嘗試寫入注冊表
internal static void SetTrustPromptBehavior() { RegistryKey key; if (System.Environment.Is64BitOperatingSystem) { key=Microsoft.Win32.Registry.LocalMachine.CreateSubKey( @"SOFTWARE\Wow6432Node\MICROSOFT\.NETFramework\Security\TrustManager\PromptingLevel"); } else { key=Microsoft.Win32.Registry.LocalMachine.CreateSubKey( @"SOFTWARE\MICROSOFT\.NETFramework\Security\TrustManager\PromptingLevel"); } key.SetValue("MyComputer", "Enabled"); key.SetValue("LocalIntranet", "Enabled"); key.SetValue("Internet", "Enabled"); key.SetValue("TrustedSites", "Enabled"); key.SetValue("UntrustedSites", "Enabled"); key.Close(); }
-
下載VSTO安裝文件位隶,運行
這一步事實上是下載了VSTO-ClickOnce的setup.exe文件并自動運行private async Task SetUpAsync() { string localFullName = $"{DownloadPath}setup.exe"; Uri uri = new Uri("http://Public.mujiannan.me/1Math/setup.exe"); Reportor.Report($"下載{uri.AbsolutePath}至{localFullName},請耐心等待..."); await DownloadAsync(uri, localFullName); System.Diagnostics.Process.Start(localFullName); }
下面是我制作的安裝器的后臺主方法:
public async Task StartInstallerAsync() { //進行兩步操作(導(dǎo)入證書开皿、注入注冊表) //優(yōu)先選擇導(dǎo)入證書涧黄,如果證書導(dǎo)入失敗,則轉(zhuǎn)而嘗試注冊表 //當(dāng)兩步操作都失敗時赋荆,向外傳遞異常信息 string errInfo = string.Empty;//用于記錄錯誤信息 bool trustSuccess = false;//標(biāo)記證書是否導(dǎo)入成功 try { await CertAsync();//導(dǎo)入證書 trustSuccess = true; } catch (Exception Ex) { errInfo += Ex.Message;//記錄證書導(dǎo)入錯誤消息 Reportor.Report("錯誤:證書導(dǎo)入失敗笋妥,請聯(lián)網(wǎng)并使用管理員權(quán)限運行"); } if (!trustSuccess) { try//事實上,如果上一步證書沒導(dǎo)入成功糠睡,再來嘗試寫注冊表也基本上是無濟于事的 { Reg.SetTrustPromptBehavior();//寫入注冊表 trustSuccess = true; } catch (Exception Ex) { errInfo += Ex.Message; this.Reportor.Report("錯誤:注冊表寫入失敗挽鞠,請嘗試使用管理員權(quán)限運行"); } } if (trustSuccess)//當(dāng)導(dǎo)入證書與注冊表寫入有任何一項成功時,都可以正常執(zhí)行下載狈孔、安裝的操作 { await SetUpAsync(); } else { await Task.Delay(2000);//顯示最終的錯誤信息前信认,留點時間告訴用戶要用管理員權(quán)限運行 throw new Exception(errInfo);//別在本地存日志之類的,直接顯示出來吧…… } }
-
發(fā)布安裝器
你應(yīng)該只把安裝器發(fā)布給最終用戶均抽,用戶在你的站點上或通過其它渠道下載安裝器嫁赏,這個安裝器將如期運行:自動下載證書、自動導(dǎo)入證書油挥、自動下載VSTO-ClickOnce的setup.exe文件潦蝇、自動安裝VSTO款熬。
后記
作為一名非科班出身的編程初學(xué)者,一些像VSTO分發(fā)之類在專業(yè)開發(fā)者眼中可能根本不能算是問題的問題也會成為我的攔路虎攘乒。
我相信專業(yè)的開發(fā)者們總能很自然地處理好這些事情贤牛,但我知道,還有一些跟我一樣自學(xué)入門的開發(fā)者們在面對這些問題時也是頭疼不已则酝。
希望這篇文章可以幫助到一些人處理好無商業(yè)證書場景下的VSTO分發(fā)問題殉簸。
學(xué)習(xí)路上,一帆風(fēng)順沽讹!