1. 程式人生 > >Wix打包系列 (六)製作升級和補丁包

Wix打包系列 (六)製作升級和補丁包

 前面我們已經知道怎麼製作一個完整安裝包了,但我們的軟體往往不能一次性就滿足客戶的需要,當客戶需要我們給軟體進行升級的時候,我們應該怎麼做呢?

    在這之前,我們有必要了解下Windows Installer中的Upgrades定義:

    6.1 關於Windows Installer Upgrades

    在Windows Installer中將軟體產品的更新劃分為3類:

  • Small updates    它意味著安裝包裡一個或幾個檔案的很小的改變,使用Small updates時不需要改變Version屬性,也不需要改變Product GUID和UpgradeCode屬性。唯一要改變的只有Package GUID,
    事實上我們每次重新生成安裝包都需要改變Package GUI。如果是同一安裝包,即Package GUID不改變,你在安裝程式後,再點選安裝包,會彈出維護的介面(解除安裝和修復);如果是Package GUID改變了,則會彈出錯誤:“已安裝了該產品的另一個版本。無法繼續安裝此版本…”。

注意任何時候重新生成安裝包一定要更改Package GUID,使用不同的Package GUID可以方便管理安裝的更新包(msp),不同的Package使用相同的GUID會造成安裝程式混亂,造成意想不到的後果。那麼既然Small updates時更改Package GUID後執行會彈出錯誤,那麼怎麼應用Small updates

呢?我們可以用命令列方式執行安裝程式,或者通過執行Patch更新包(msp)。製作Patch更新包後面會詳細講,我們先看看命令列方式:

msiexec /fvomus [path to updated .msi file] 
或者 
msiexec /I [path to updated msi file] REINSTALL=ALL REINSTALLMODE=vomus. 
  • Minor upgrades 在這種情況下,需要更改product version,當然Package GUID也要改變,Product GUIDUpgradeCode屬性仍然保持不變。這種方式允許我們新增新的features
    components,但是不能改變feature-component樹的組織結構。Minor upgradesSmall updates很相似,似乎只是多了個版本變化而已;事實上,可以用Small updates的地方肯定也可以用Minor upgrades,應用Minor upgrades的方式跟應用 Small updates一樣,可以使用命令列或者patch方式。
  • Major upgrades 在這種情況下,需要更改Version 屬性, Product  Package GUID,我們仍然保持UpgradeCode屬性不變,大家可能會注意到,UpgradeCode在這裡似乎沒什麼用處,先別急,下面我們會馬上講到它的用處。先看看Major upgrades ,事實上,對開發人員來說,它是一個最安全和最便捷的升級方式,因為Product GUID已經改變,意味著它可以和老版本共存安裝到一臺計算機上,並且是一個完全的全新安裝。

        關於Product/@Id屬性(GUID),Product/@Version屬性,Product/@UpgradeCode屬性(GUID),還有Package/@Id屬性(GUID);這幾個屬性在第一章有提到過,在這裡我們就可以更清楚他們的意義了

    6.2 檢測並替換現有版本(Major upgrades

    講到這裡,大家應該對Windows Installer製作升級的基礎知識有了一定的瞭解。但是如果我們的安裝包體積不大,希望使用Major upgrades,但是又不想每次安裝新版本時要手動解除安裝以前的版本,要怎麼做呢?

    最好是方式是讓安裝程式能檢測以前版本,然後刪除以前版本,最後安裝新版本程式;要想能檢測到以前版本的資訊,這時UpgradeCode就起到作用了。當我們製作更新包或升級版本時,首要要確保我們有以前老的版本的安裝包;另外就算我們不打算當前版本被升級,也必須包含UpgradeCode屬性,因為一旦你沒提供UpgradeCode屬性,以後就沒有辦法再提供了;我們還應該知道什麼時候應該改變UpgradeCode屬性,事實上,我們在開發一個專案時,可以一直保持UpgradeCode不變,即使Product GUID已經改變,當然你也可以改變UpgradeCode以更好的管理程式版本。

    要解決我們的問題還需要引入UpgradeVersion標籤,它能幫助我們檢測已安裝的版本資訊和將要升級的版本資訊。

<Upgrade Id="F4F8195E-E907-42dd-BB90-CC2403FA7384">
    <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND" 
        Minimum="1.0.0" IncludeMinimum="yes" 
        Maximum="$(var.Version)" IncludeMaximum="no" />
    <UpgradeVersion OnlyDetect="yes" Property="NEWERFOUND" 
        Minimum="$(var.Version)" IncludeMinimum="no" />
</Upgrade>

    Upgrade的Id屬性是我們安裝的以前版本的UpgradeCode,如果你的程式應用了多個UpgradeCode,那麼你只需要新增一個新的Upgrade標記就可以了,每個Upgrade標記包含自己的版本範圍。我們可以看出來,要想更好的管理版本,我們不應該頻繁更換UpgradeCode,不然這裡就要寫很多個Upgrade標記了,對應還要寫很多custom action;我們最多在每個大版本的時候更換UpgradeCode就足夠了,比如1.x版本時使用一個UpgradeCode,2.x時使用另外一個UpgradeCode;當然你也可以選擇不更換UpgradeCode。

    Minimum 和 Maximum指定Upgrade中我們應該升級的版本範圍,IncludeMaximum 和 IncludeMinimum 指定升級範圍是否包含邊界值(IncludeMinimum='no' 表示只查詢以上版本)。

使用Upgrade 標記後將會觸發一個新的標準動作FindRelatedProducts,它在LaunchConditions動作後執行,當然我們可以在InstallExecuteSequence中重定義它的執行順序,但一般情況下我們不用這麼做。FindRelatedProducts動作 通過Upgrade 標記檢查其中的所有版本,如果找到了,則它的Product GUID將會被追加到UpgradeVersion標記中指定的Property中(如示例中的PREVIOUSFOUND和NEWERFOUND);這裡的UpgradeVersionProperty屬性,相當於定義了2個Property:PREVIOUSFOUND和NEWERFOUND。

    OnlyDetect='yes' 告訴我們安裝程式不會移除以前的程式嗎,如果我們是Major upgrades ,將OnlyDetect置為no,則會刪除以前版本的程式,從而可以保證目標計算機中只有一個版本的product;如果是Minor upgrades ,我們需要將OnlyDetect置為yes。

如果開發一個本地化的軟體包,你也可以在UpgradeVersion 中指定Language屬性

   注意在這裡我定義了2個UpgradeVersion,他們的Property屬性分別是PREVIOUSFOUND和NEWERFOUND。PREVIOUSFOUND是查詢以前安裝的版本,最低版本是1.0.0,它是始終不變的;最大版本是當前版本,需要在編譯的傳進來,這樣做的目的是每次改變版本不用去修改原始碼中的版本號;OnlyDetect置為no表示會刪除掉找到的安裝程式版本。比如當前版本是3.0.2,則在安裝當前版本過程中,在版本1.0.0和3.0.2之間的任何版本都會被刪除,包括修訂版本。移除以前版本完全是自動的,如果我們要在移除以前版本前做任何事情,我們可以寫一個custom action,設定它的conditionUPGRADINGPRODUCTCODE 屬性的值。Windows Installer只是在自動刪除的程序裡才會設定這個屬性,在新增/刪除程式裡手動刪除程式不會設定該屬性的值。

     那麼為什麼要設定NEWERFOUND呢,試想如果你已經安裝了2.0版本的程式,然後又安裝1.0的版本的程式,一般情況下安裝會正常進行,安裝程式不能自動刪除新版本的程式,這時候我們檢測到新版本程式後就需要彈出錯誤提示,提示使用者已安裝更新的版本。如何做到這點呢,我們需要新增一個custom action,以下程式碼在FindRelatedProducts後如果找到新版本,則會執行NoDowngrade 的custom action,該action會彈出一個錯誤提示,阻止安裝程式繼續執行。

<CustomAction Id='NoDowngrade' Error='已經安裝了較新版本的 [ProductName],無法繼續安裝該版本應用程式 .' />

 <InstallExecuteSequence>
     <Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
 </InstallExecuteSequence>
    6.3 製作升級補丁(Minor upgrades And Small updates

    到這裡大家應該知道為什麼我說Major upgrades 是最安全的,因為不管你之前安裝的是什麼版本,都會刪除掉然後安裝當前版本。而對於Minor upgrades,你需要針對每個不同版本安裝包製作Patch更新包(msp),比如從1.1.0到1.1.1,從1.1.1到1.1.2,如果想從1.1.0到1.1.2,則需要重新制作Patch更新包(msp),當然也不是不可以製作通用於所有版本的Patch更新包(msp),前提是你要有所有版本安裝包(msi),製作方法相對也比較繁瑣,而且Minor upgrades還有諸多限制,如果處理不好會導致安裝錯誤。當然如果你的安裝檔案體積太大,使用Major upgrades 就不合適了,一般情況下我們使用Minor upgrades ,下面我們就看看如何為Minor upgrades 製作Patch更新包(msp)。

    製作製作Patch更新包之前,需要注意以下情形:

  • 當你需要新老版本共存時,則必須使用Major upgrades。
  • 當你需要更改生成的msi檔名稱的時候,不能使用Minor upgradesSmall updates
  • 當你更改了Packge裡任何Component的GUID時,不能使用Minor upgradesSmall updates
  • 當有元件被移除時,不能使用Minor upgradesSmall updates
  • 當更改了Feature的組織結構,比如在Feature中新增或刪除子Feature時,不能使用Minor upgradesSmall updates

    如果新版本滿足這些條件,我們就可以開始製作更新包了,  這裡我們將在新版本(1.0.1)安裝中新增一個dll檔案,然後更改exe執行檔案。製作步驟如下:

    1、編譯生成1.0.0版本安裝檔案

candle.exe -dVersion=1.0.0  -ext WixUtilExtension -ext WixSqlExtension Sample.wxs DbConfigDlg.wxs -out 1.0.0/
light.exe -loc WixUI_zh-cn.wxl  -ext WixUIExtension -ext WixUtilExtension -ext WixSqlExtension -out 1.0.0/Sample.msi 1.0.0/Sample.wixobj 1.0.0/DbConfigDlg.wixobj 

    2、 接著把1.0.0資料夾的內容複製到新的資料夾1.0.1中,用記事本隨意修改FoobarAppl10.exe檔案和Manual.pdf檔案,以區別於1.0.0版本; 

   3、編譯生成1.0.1版本安裝檔案

candle.exe -dVersion=1.0.1  -ext WixUtilExtension -ext WixSqlExtension Sample.wxs DbConfigDlg.wxs -out 1.0.1/
light.exe -loc WixUI_zh-cn.wxl  -ext WixUIExtension -ext WixUtilExtension -ext WixSqlExtension -out 1.0.1/Sample.msi 1.0.1/Sample.wixobj 1.0.1/DbConfigDlg.wixobj 
   4、建立wix原始檔Patch.wxs,內容如下:
<?xml version='1.0' encoding='utf-8'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
    <Patch AllowRemoval='yes' Manufacturer='Acme Ltd.' MoreInfoURL='www.acmefoobar.com' 
           DisplayName='Police1.0.1.0 Patch' Description='Minor Update Patch' Classification='Update'>
        <Media Id='5000' Cabinet='SamplePatch.cab'>
            <PatchBaseline Id='SamplePatch' />
        </Media>
        <PatchFamily Id='SamplePatchFamily' Version='1.0.0.0' Supersede='yes'>
            <ComponentRef Id='compMainExecutable'/>
            <ComponentRef Id='compManual'/>
        </PatchFamily>
    </Patch>
</Wix>

    Classification屬性可以是:Hotfix, Security Rollup, Critical Update, Update, Service Pack or Update Rollup。AllowRemoval 屬性確定使用者在以後是否能夠解除安裝該補丁包。

    PatchFamily 標記包含要被修補的專案,Supersede決定是否目前的補丁包替換掉相同的系列裡的所有以前的補丁包。PatchFamily 的子元素可以是ComponentRef或者FeatureRef等是對Sample.wxs檔案中的元素引用,表示版本間不同的地方

    5、使用另外一個wix工具torch在兩個安裝包之間來建立一個transform檔案。命令列引數-xi指示程式使用wix自己的格式.wixpdb 和.wixmst,而不是Windows Installer格式 (.msi and .mst)。

torch.exe -p -xi 1.0.0/Sample.wixpdb 1.0.1/Sample.wixpdb -out Patch.wixmst
    注意執行torch命令所在資料夾不能包含中文,否則執行會出現檔案不存在的錯誤     6、使用wix編譯器和聯結器生成補丁包,但是這次輸出格式跟往常不一樣,是.wixmsp格式的。在這裡不需要告訴linker生成這種型別的檔案,linker將根據原始檔的內容自動決定生成什麼格式的檔案。
candle.exe Patch.wxs
light.exe Patch.wixobj
    7、最後,我們用上一步生成的wixmsp檔案和剛才生成的transform檔案來建立目前的Windows Installer 補丁包。Pyro是負責生成補丁包的wix工具,它不僅需要transform檔名,還需要相應的PatchBaseline/@Id屬性,最好是用命令列模式:
pyro.exe Patch.wixmsp -out Patch.msp -t SamplePatch Patch.wixmst

生成的patch.msp就是修補安裝程式,為了測試它,我們先安裝原始安裝包(Error/Product.msi),然後新增修補程式:

msiexec /p Patch.msp

檢查檔案是否真的被更新成新版本了。接著到新增/刪除程式,選擇顯示更新,並移除第一個補丁,所做的更改將恢復到更新前的狀態。

    這裡介紹的只是1對1版本的升級,也可以同時為多個不同的舊版本製作最終版本的升級包,有興趣的可以參考sdk文件。下一章我們將介紹如何新增系統必備元件的安裝程式。

相關推薦

Wix打包系列 製作升級補丁

 前面我們已經知道怎麼製作一個完整安裝包了,但我們的軟體往往不能一次性就滿足客戶的需要,當客戶需要我們給軟體進行升級的時候,我們應該怎麼做呢?     在這之前,我們有必要了解下Windows Installer中的Upgrades定義:     6.1 關於Wi

C語言系列結構體聯合體

結構體 在C語言中,可以使用結構體(Struct)來存放一組不同型別的資料。結構體的定義形式為: struct 結構體名{ 結構體所包含的變數或陣列 }; 結構體是一種集合,它裡面包含了多個變數或陣列,它們的型別可以相同,也可以不同,每

Hive 系列—— Hive 檢視索引

一、檢視 1.1 簡介 Hive 中的檢視和 RDBMS 中檢視的概念一致,都是一組資料的邏輯表示,本質上就是一條 SELECT 語句的結果集。檢視是純粹的邏輯物件,沒有關聯的儲存 (Hive 3.0.0 引入的物化檢視除外),當查詢引用檢視時,Hive 可以將檢視的定義與查詢結合起來,例如將查詢中的過濾器推

物聯網平臺構架系列 :Amazon, Microsoft, IBM IoT 解決方案導論 之 結語

物聯網; iot; aws; 亞馬遜; greengrass;microsoft; azure;ibm; watson; bluemix最近研究了一些物聯網平臺技術資料,以做選型參考。腦子裏積累大量信息,便想寫出來做一些普及。作為科普文章,力爭通俗易懂,不確保概念嚴謹性。我會給考據癖者提供相關英文鏈接,以便深

elasticsearch系列備份

indices stat 必須 tor 信息 操作 accepted gui 配置 快照備份 1.創建文件倉庫 1.1 在$ELASTICSEARCH_HOME/config/elasticsearch.yaml中增加配置 #這個路徑elasticsearch必須有權限訪問

Linq To Sql進階系列用object的動態查詢與保存log篇

directory ont 簡單 lambda表達式 bind add dbo 所有 生成 動態的生成sql語句,根據不同的條件構造不同的where字句,是拼接sql 字符串的好處。而Linq的推出,是為了彌補編程中的 Data != Object 的問題。我們又該如何實現

【原創】源碼角度分析Android的消息機制系列——Handler的工作原理

urn long empty isa pat stat 開啟 it is performed ι 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 先看Handler的定義: /** * A Handler allows you to send and proc

C語言學習系列存儲類

amp 限制 () 存儲 col print strong .com 學習 一、C存儲類 存儲類定義C程序中變量/函數的範圍(可見性)和生命周期。這些說明符放置在他們所修飾的類型之前。for example:auto、register、static、extern。 (一)、

C語言學習系列基本語法

xor 12px 左移 程序 str 繼續 p s type false 一、C運算符 算術運算符(語法和java類似或基本一樣略過不再描述) 關系運算符(略) 邏輯運算符(略) 位運算符 運算符描述實例 & 如果同時存在於兩個操作數中,二

Python操作rabbitmq系列:進行RPC調用

block 異常 遠程 轉換 調用 成了 mage chang 多少 此刻,我們已經進入第6章,是官方的最後一個環節,但是,並非本系列的最後一個環節。因為在實戰中還有一些經驗教訓,並沒體現出來。由於馬上要給同事沒培訓celery了。我也來不及寫太多。等後面,我們再慢慢補充。

IT輪子系列——Excel上傳與解析,一套代碼解決所有Excel業務上傳,你Get到了嗎

tryparse mappath src 個推 列名 import ges bject tab 前言 在日常開發當中,excel的上傳與解析是很常見的。根據業務不同,解析的數據模型也都不一樣。不同的數據模型也就需要不同的校驗邏輯,這往往需要寫多套的代碼進行字段的檢驗,如必填

Scala入門系列:面向對象之object

所有 name 應用 eight lac box dfa port clas object Person { private var eyeNum = 2 println("this Person object") def getEyeNum = eyeNum

Docker入門與應用系列Docker私有與公共鏡像倉庫

nbsp one 默認 span epo refers 1.8 png list 1.搭建私有鏡像倉庫Docker Hub作為Docker默認官方公共鏡像;如果想搭建自己的私有鏡像倉庫,官方提供registry鏡像,使搭建私有倉庫非常簡單1.1.1下載registry鏡像並

SSM框架開發web項目系列 SpringMVC入門

商品 rwx tmx quest npv you odm pci vdp   前言   我們最初的javaSE部分學習後,基本算是入門了,也熟悉了Java的語法和一些常用API,然後再深入到數據庫操作、WEB程序開發,漸漸會接觸到JDBC、Servlet/Jsp之類的知識,

Tokyo TyrantTTServer系列-數據丟失誰的錯

內存數據庫 emca aps csdn AC cell class mon cached 前面的一些文章講到了memcache以及TT。memcache內存數據庫非常

vue 開發系列 企業微信整合

狀態 choose tin getent reset .post hal imp random 概述 手機端程序可以和企業微信進行整合,我們也可以使用企業微信JSSDK功能,實現一些原生的功能。 整合步驟 在整合之前需要閱讀 整合步驟。 http://work

Java 設計模式系列適配器模式

建議 技術 amp (六) image 必須 一起 nts 工作 Java 設計模式系列(六)適配器模式 適配器模式把一個類的接口變換成客戶端所期待的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 適配器模式的結構: 類的適配器模式 對象的

Greeplum 系列 備份與恢復

移除 cat eat 適合 主機 pdb SQ 簡單 mail Greeplum 系列(六) 備份與恢復 一、備份 1.1 並行備份(gp_dump) GP 同時備份 Master 和所有活動的 Segment 實例,備份消耗的時間與系統中實例的數量沒有關系。在 Maste

springboot系列 使用模板引擎

RKE 系列 spring tail tar https blank log 詳細介紹 這裏就轉載一篇大牛的文章 https://blog.csdn.net/caychen/article/details/79625927 這篇文章詳細介紹了thymeleaf和freema

WCF系列 - WCF安全系列 - basicHttpBinding

工具 安裝服務 請求 log gconf body primary 域名 規範 綁定可指定在與終結點通話時所使用的通信機制,並指示如何連接到終結點。綁定由一些元素組成,這些元素指定如何對 Windows Communication Foundation (WCF) 通道進行