無商業(yè)證書場景下的VSTO分發(fā)方案

前言

本文旨在優(yōu)化無商業(yè)證書場景下的VSTO分發(fā)方案蜕衡,目標(biāo)是實現(xiàn)用戶端的簡單安裝斟冕、自動更新逃顶。

項目介紹

我花費幾個月時間斷斷續(xù)續(xù)折騰出了一個Excel VSTO托呕,曾在分發(fā)階段遭遇了許多問題。
雖然麻煩不斷券盅,但通過不斷努力(地搜索)帮哈,最終得到了一套比較完善的方案,遂撰文分享一二锰镀。
主要思路:在VSTO的ClickOnce之前套一層安裝器娘侍,進行證書導(dǎo)入等操作,之后自動下載VSTO安裝包泳炉、自動運行憾筏。

  1. 自制證書
  2. 給VSTO簽名
  3. 發(fā)布VSTO
  4. 自制安裝器
    1. 安裝器關(guān)鍵方法一:嘗試下載自制證書,并導(dǎo)入用戶機器
    2. 安裝器關(guān)鍵方法二:若證書導(dǎo)入失敗花鹅,則嘗試寫入注冊表
    3. 安裝器關(guān)鍵方法三:下載VSTO安裝文件氧腰,運行
  5. 發(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)油额。

publishfolderstructure

這種發(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)站,甚至還妄想它能夠保持自動更新……那么舍杜,你會得到這個:

截圖來自網(wǎng)絡(luò)

當(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安裝包箍铭、自動運行。

  1. 自制證書
    工具任選椎镣,自制一個代碼證書诈火,最終效果差不多是這樣:

    自制證書

    如果你不知道如何自制證書,那么可以從這里得到幫助状答。
    注意冷守,面向公眾的商業(yè)用途切勿使用自制證書,這是對自己和客戶負責(zé)惊科。如果非要使用自制證書拍摇,也請制作一個單獨的代碼簽名證書,萬不可在客戶機器上安裝根證書馆截,因為一旦被有心人曝光充活,你的企業(yè)很可能成為千夫所指。

  2. 給VSTO簽名

    使用自制證書給VSTO簽名

  3. 發(fā)布VSTO
    雖然你使用了不受用戶信任的自制證書,但你可以假裝它是正規(guī)商業(yè)證書堪唐,直接把你的VSTO發(fā)布到站點上就是了巡语。
    到此為止,你已經(jīng)成功獲得了一個用戶無法安裝的VSTO淮菠。它應(yīng)該會有一個類似于“setup.exe”的文件男公,不要讓用戶直接下載它,它應(yīng)該由你的自制安裝器下載到用戶電腦上合陵。

  4. 自制安裝器
    它的名字可能會類似于“Installer.exe”枢赔,既可以是命令行腳本也可以是擁有華麗界面的WPF程序,這些都不重要拥知,你可以隨心所欲踏拜。
    重要的是,它應(yīng)該是一個單文件軟件低剔,開袋即食的那種單文件軟件速梗,以方便用戶下載、直接點擊運行襟齿。
    它的作用主要有以下三點姻锁,我將以代碼說明:

    1. 嘗試下載自制證書,并導(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);
                }
            }
        }
      
    2. 若證書導(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();
        }
      
    3. 下載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);//別在本地存日志之類的,直接顯示出來吧……
         }
     }
    
  5. 發(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)順沽讹!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末般卑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子爽雄,更是在濱河造成了極大的恐慌蝠检,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挚瘟,死亡現(xiàn)場離奇詭異叹谁,居然都是意外死亡,警方通過查閱死者的電腦和手機刽沾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門本慕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侧漓,你說我怎么就攤上這事〖嗲猓” “怎么了布蔗?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長浪腐。 經(jīng)常有香客問我纵揍,道長,這世上最難降的妖魔是什么议街? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任泽谨,我火速辦了婚禮,結(jié)果婚禮上特漩,老公的妹妹穿的比我還像新娘吧雹。我一直安慰自己,他們只是感情好涂身,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布雄卷。 她就那樣靜靜地躺著,像睡著了一般蛤售。 火紅的嫁衣襯著肌膚如雪丁鹉。 梳的紋絲不亂的頭發(fā)上妒潭,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天,我揣著相機與錄音揣钦,去河邊找鬼雳灾。 笑死,一個胖子當(dāng)著我的面吹牛冯凹,可吹牛的內(nèi)容都是我干的佑女。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼谈竿,長吁一口氣:“原來是場噩夢啊……” “哼团驱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起空凸,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嚎花,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后呀洲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體紊选,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年道逗,在試婚紗的時候發(fā)現(xiàn)自己被綠了兵罢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡滓窍,死狀恐怖卖词,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吏夯,我是刑警寧澤此蜈,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站噪生,受9級特大地震影響裆赵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜跺嗽,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一战授、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桨嫁,春花似錦植兰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肚逸,卻和暖如春爷辙,著一層夾襖步出監(jiān)牢的瞬間彬坏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工膝晾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留烛恤,地道東北人巢钓。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親几睛。 傳聞我的和親對象是個殘疾皇子泻仙,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容