使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一&二)——初识WiX

转载fromVan Pan 的专栏

 

http://blog.csdn.net/rryqsh/article/details/8274832

http://blog.csdn.net/rryqsh/article/details/8277585

 

Visual Studio 打包安装七宗罪

 

        开发.NET的人,肯定会使用Visual Studio里面自带的MSI打包安装工具框架。如果是在一般情况下,这个打包安装框架已经完全足够满足产品发布安装的需要了。它的制成品,是一个 setup.exe,一个MSI安装文件,如果你选择项目以来的其他.NET,Windows Install 框架,并且确定随产品发布,那制成品中还会包含这些东西的安装文件。

 

        但是VS打包发布出来的安装包,安装体验实在是非常差,举个例子,如果你的项目是依赖于.NET 4.0以及VC++ 2010,并且你的目标客户机中没有安装过任何该类产品,那当你执行setup.exe的时候,先是会弹出.NET 4.0客户安装协议,用户点击“同意”后,再弹出VC++ 2010客户安装协议,用户再次点击“同意”,才能开始真正安装。并且在安装过程中,每安装一个东西,如果是在Vista之上的系统上,就会弹出一次需要确认安装并且提升权限的对话框,实在是不胜其烦。

 

        并且这个打包的选项也非常奇怪,如果会使用Installer发布工具的,就会记得里面永远只能在“网上下载所需依赖项”和“本地包含所需依赖项”中二选 其一。那如果我想定制发布安装包,如果发现依赖项不存在,再自动去网上下载呢?不好意思,做不到。而且如果我打包出来的MSI是中文的,那发布的时候必定 会带上.NET的中文语言包。如果不是修改系统的bootstrapper配置,这个语言包就是必须跟着的,真是完全无厘头,我产品是多语言安装的,难 道.NET也要多语言包吗?

 

必须掌握的一些基础概念

 

        Wix的全称是(Windows Installer XML),简而言之,就是用XML来配置和定制个性化的安装方案。其中一部分称为Burn,是本文接下去要着重介绍的Bootstrapper开发框架,另一部分则为Setup开发框架。

 

        先说一下Bootstrapper和MSI的区别,MSI是微软比较新的一套安装解决方案,依赖于Microsoft Install Service,其实MSI可以理解为一套强格式的安装库,MSI文件中包含了一系列数据结构和文件,数据结构说明了例如要创建哪些目录,要创建哪些注册 表项,要拷贝哪些文件到哪些目录中,创建什么快捷方式等配置信息,以及需要拷贝发布的所有文件数据。然后安装服务通过这些配置信息,读取并一步步执行,最 终就完成了一个MSI的安装过程。MSI文件就是一个更强大的压缩文件安装包。

 

        问题是如果你的城西使用纯C++开发的,那只要一个MSI发布就解决问题了,因为发布以后不依赖于其他东西可以直接执行。但是既然你用了微软的东西,现 在.NET几乎是Windows上必须会涉及的框架,那大多数程序都会依赖于.NET。这时候问题就来了,如果客户机上没有安装.NET,怎么办?你又不 能把.NET单独带在你的MSI中一起发布。这个时候就需要在安装MSI之前判断一下系统的安装环境,比如有没有安装.NET,如果已经装了就不用再安装 了,当然其他的一些框架也需要判断,这些提前判断的事情MSI是做不了的,当然你的程序也做不了,因为还没有.NET环境啊,你的程序是用.NET写的! 这不是鸡生蛋蛋生鸡的问题吗?

 

        这些问题其实微软也想到了,因此他们自己做了一个简单的setup.exe,你看,这个是exe文件,不依赖于任何其他框架,这个exe会先判断系统环 境,并且做出需要下载安装其他框架的决定,然后等基础环境搞定了,就可以安装后我们的MSI了。这个exe,就被称为bootstrapper。

 

WiX Bootstrapper开发教程

 

        以上所说的这些问题,在WiX中都可以得到解决,当然你甚至可以不用VS的打包发布工具,因为之前我们已经知道,WiX可以开发自己的MSI,只是文本对 这个不再详述,VS的打包工具制作出MSI,再用WiX的Bootstrapper安装,相得益彰,省时省力,WiX毕竟只能XML编写,还是很麻烦的。

 

        首先,我们在http://wixtoolset.org/releases中 下载WiX Toolset安装文件,VS 2010好像最多支持到3.7版本,然后点击中间齿轮的那一行Install进行框架安装。这个工具是支持VS插件的,安装完成后,VS中就会多出一种项 目类型“Wix Toolset”,并且选中后我们选择“Bootstrapper Project”,即可创建出新项目,我们在这个项目中进行我们的bootstrapper开发。

 

 使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一&二)——初识WiX_第1张图片

 

 使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一&二)——初识WiX_第2张图片

 

        创建完成后,就会多出一个Bootstrapper项目,其中有Bundle.wxs文件,这个文件就是打包安装配置文件。所有的XML元素,都可以通过http://wix.sourceforge.net/manual-wix3/schema_index.htm查询,默认代码如下:

[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">  
  3.     <Bundle Name="Bootstrapper1" Version="1.0.0.0" Manufacturer="" UpgradeCode="5240b0e0-2b53-44c9-9837-05e9a4b63dbc">  
  4.         <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />  
  5.   
  6.         <Chain>  
  7.             <!-- TODO: Define the list of chained packages. -->  
  8.             <!-- <MsiPackage SourceFile="path\to\your.msi" /> -->  
  9.         </Chain>  
  10.     </Bundle>  
  11. </Wix>  

        下面我们来逐个标签元素来看一下这个文件是如何影响运行的

        Bundle,这个是所有配置的根节点,其中Name就是我们发布的产品名称,可自定义,注意该名称会出现在安装对话框的标题栏以及卸载程序列表中的名 称。Version是版本号,Manufacturer是开发者名称,这些都会出现在卸载程序列表中,UpdateCode是很重要的属性,如果两个产品 的UpdateCode一样,那Version更大的产品会自动将小版本程序卸载后再安装,也就是自动的覆盖安装。这些概念都是所有的安装框架通用的。

 

        BootstrapperApplicationRef这个概念比较复杂,按照我使用下来的经验,这个就是使用已经定义完成的安装框架模 板,Id="WixStandardBootstrapperApplication.RtfLicense"是一个已经现有的安装框架界面,表示这个 Bootstrapper执行后会显示一个客户安装协议对话框,对话框中的文本是可以自定义的。我们会在之后的篇幅中讲到这个元素的详细自定义。

 

        Chain,这个就是表示安装的序列,所有的自定义安装顺序就在这个节点中完成,比如我们可以先定义安装a.exe,再安装b.msi,再安装c.msp等等,都可以在这个节点中进行配置。

 

        我们来编辑一下wxs文件,指定Bundle/@Manufacturer的属性内容,以及为Chain增加一个子节点,Chain节点中必须有一个子节点,我们可以随便生成一个.msi安装文件,然后复制到我们的bootstrapper项目中,然后增加Chain中的子元素Msi,并且生成一下这个工程,最后的wxs文件如下:

[html] view plain copy
  1. <span style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">  
  3.     <Bundle Name="DemoWixBootstrapper" Version="1.0.0.0" Manufacturer="VanPan" UpgradeCode="5240b0e0-2b53-44c9-9837-05e9a4b63dbc">  
  4.     <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense"/>  
  5.         <Chain>  
  6.       <MsiPackage SourceFile="Setup1.msi"/>  
  7.         </Chain>  
  8.     </Bundle>  
  9. </Wix></span>  


        其中Setup1.msi文件,就是随便拿VS生成的一个Install成品MSI,你也可以使用你自己的项目MSI替换之。生成后,在项目的Debug 文件夹内,就会看到有一个Bootstrapper1.exe文件,大小比我们放入的Setup1.msi略大,其实这个就是把MSI打包到安装exe中 的结果。双击一下exe,就能看到安装画面了。

 使用WiX Toolset创建.NET程序发布Bootstrapper(安装策略管理)(一&二)——初识WiX_第3张图片

 

        我们看到,标题栏就是我们自定义的Bundle/@Name属性内容,你可以自己点击一下Install按钮体验一下安装的效果,当然这个还是一个非常粗糙的样品。请放心,这个框架绝对绝对不会和你想象得那么简单。我们后面的文章再继续详解如何自定义安装序列,自定义安装协议,本地化安装界面,甚至调整安装界面布局。zhuan

 

自定义产品卸载方式

      

        继续从上一次的基础上前进,现在我们已经知道了最简单的bootstrapper打包方法,现在我们对其中的每个节点深入自定义,争取可以达到我们需要的效果。先把最后全部的XML贴出来。

[html] view plain copy
  1. <span style="font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>  
  2. <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"   
  3.      xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" >  
  4.   <Bundle Name="CamCard" Version="4.0.0.0" Manufacturer="IntSig Information Co., Ltd." AboutUrl="http://www.intsig.net" IconSourceFile="icon_256.ico"    
  5.           UpgradeCode="1EB9EC76-9E5F-4471-B522-314A62518A80" DisableRemove="no" DisableModify="yes" DisableRepair="yes">  
  6.     <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">  
  7.       <bal:WixStandardBootstrapperApplication LicenseFile="license.rtf" ThemeFile="MyTheme.xml" LocalizationFile="MyLocalize.wxl" LogoFile="logo.png" />  
  8.     </BootstrapperApplicationRef>  
  9.     <Chain>  
  10.       <ExePackage Id="Netfx4Full"  
  11.           Cache="no"  
  12.           Compressed="no"  
  13.           PerMachine="yes"  
  14.           Permanent="yes"  
  15.           Vital="yes" InstallCommand=" /q /norestart"  
  16.           SourceFile="dotNetFx40_Full_x86_x64.exe"  
  17.           DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=164193"  
  18.           DetectCondition="DotNetFramework40FullInstallRegValue=1" />  
  19.       <MsiPackage Compressed="no" SourceFile="SSCERuntime-CHS.msi" Vital="yes" DisplayInternalUI="no" Permanent="yes" ForcePerMachine="yes"  
  20.           DownloadUrl="http://go.microsoft.com/fwlink/?LinkID=166085"  
  21.           InstallCondition="VersionNT = v5.1" />  
  22.       <MsiPackage Compressed="no" SourceFile="IntSig.CamCard.Installer.msi" Vital="yes" DisplayInternalUI="no" Permanent="no"  ForcePerMachine="yes">  
  23.         <MsiProperty Name="TARGETDIR" Value="[InstallFolder]"/>  
  24.       </MsiPackage>  
  25.     </Chain>  
  26.     <util:RegistrySearch Id="FindDotNet40FullInstallRegValue" Root="HKLM"  
  27.                  Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" Value="Install"  
  28.                  Variable="DotNetFramework40FullInstallRegValue" />  
  29.   </Bundle>  
  30. </Wix></span>  

        Bundle节点前面几个属性我们都已经知道了,IconSourceFile就是打包后exe的图标设置,DisableRemove、 DisableModify这两个属性比较有讲究,他们分别设置了在“添加/删除程序”列表中,选中安装包后鼠标右击,是否会出现“卸载”和“修改”这两 个选项。如果这两个选项都同时为yes,那这个产品安装后根本就不会出现在“添加/删除程序”列表中,只能通过再次双击bootstrapper安装 exe进行卸载。


自定义产品安装界面

      

[html] view plain copy
  1. <span style="font-size:14px;">    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">  
  2.       <bal:WixStandardBootstrapperApplication LicenseFile="license.rtf" ThemeFile="MyTheme.xml" LocalizationFile="MyLocalize.wxl" LogoFile="logo.png" />  
  3.     </BootstrapperApplicationRef></span>  

        BootstrapperApplicationRef这个节点上一篇已经讲解过,但是我们使用的是最原始的默认界面,事实上可以通过在该节点中加入 WixStandardBootstrapperApplication来自定义安装界面。LicenseFile就是要显示在用户安装协议中的RTF文 件名称。ThemeFile是自定义主题xml文件,该文件详细定义了安装界面中的每个按钮和控件的位置。LocalizationFile是本地化配置 文件,这个版本的Burn框架还不支持运行时自动根据安装语言环境自动切换。如果你需要采用本地化安装策略,比较靠谱的方法就是在 bootstrapper之前再执行另一个exe,用来判断语言环境并自动执行不同的bootstrapper进行安装。LogoFile是安装界面左上 角那个图标,注意XP环境下好像是不能使用ICON文件的。


        ThemeFile="MyTheme.xml" 这个文件可以在WiX源代码中找到,我贴在这篇博客里面,方便大家直接复制粘贴,这文件和后面的本地化文件的确不好找。

 

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">  
  3.   <Window Width="485" Height="300" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>  
  4.   <Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>  
  5.   <Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>  
  6.   <Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>  
  7.   <Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>  
  8.   <Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font>  
  9.   
  10.   <Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/>  
  11.   <Text X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Text>  
  12.   
  13.   <Page Name="Help">  
  14.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>  
  15.     <Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>  
  16.     <Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>  
  17.   </Page>  
  18.   <Page Name="Install">  
  19.     <Richedit Name="EulaRichedit" X="11" Y="80" Width="-11" Height="-70" TabStop="yes" FontId="0" HexStyle="0x800000" />  
  20.     <Checkbox Name="EulaAcceptCheckbox" X="-11" Y="-41" Width="260" Height="17" TabStop="yes" FontId="3" HideWhenDisabled="yes">#(loc.InstallAcceptCheckbox)</Checkbox>  
  21.     <Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>  
  22.     <Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>  
  23.     <Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>  
  24.   </Page>  
  25.   <Page Name="Options">  
  26.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text>  
  27.     <Text X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Text>  
  28.     <Editbox Name="FolderEditbox" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />  
  29.     <Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">#(loc.OptionsBrowseButton)</Button>  
  30.     <Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsOkButton)</Button>  
  31.     <Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsCancelButton)</Button>  
  32.   </Page>  
  33.   <Page Name="Progress">  
  34.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>  
  35.     <Text X="11" Y="121" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>  
  36.     <Text Name="OverallProgressPackageText" X="85" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>  
  37.     <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="143" Width="-11" Height="15" />  
  38.     <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>  
  39.   </Page>  
  40.   <Page Name="Modify">  
  41.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>  
  42.     <Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>  
  43.     <Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>  
  44.     <Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>  
  45.   </Page>  
  46.   <Page Name="Success">  
  47.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.SuccessHeader)</Text>  
  48.     <Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>  
  49.     <Text Name="SuccessRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text>  
  50.     <Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>  
  51.     <Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>  
  52.   </Page>  
  53.   <Page Name="Failure">  
  54.     <Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FailureHeader)</Text>  
  55.     <Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>  
  56.     <Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" />  
  57.     <Text Name="FailureRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text>  
  58.     <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>  
  59.     <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>  
  60.   </Page>  
  61. </Theme>  

        可以看到这个XML文件可以通过自定义的方法来进行界面修改,其中#(loc.Caption)之类的是WiX使用变量的语法,这些变量都是已经内嵌在框 架中了,我们还可以通过在bundle.wxs文件中自行增加变量的方法来达到增加变量的目的。MyLocalize.wxl文件如下:

 

[html] view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <WixLocalization xmlns="http://schemas.microsoft.com/wix/2006/localization">  
  3.   <String Id="Caption">Setup [WixBundleName]</String>  
  4.   <String Id="Title">[WixBundleName]</String>  
  5.   <String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>  
  6.   <String Id="HelpHeader">Setup Help</String>  
  7.   <String Id="HelpText">  
  8.     /install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or  
  9.     creates a complete local copy of the bundle in directory. Install is the default.  
  10.   
  11.     /passive | /quiet -  displays minimal UI with no prompts or displays no UI and  
  12.     no prompts. By default UI and all prompts are displayed.  
  13.   
  14.     /norestart   - suppress any attempts to restart. By default UI will prompt before restart.  
  15.     /log log.txt - logs to a specific file. By default a log file is created in %TEMP%.  
  16.   </String>  
  17.   <String Id="HelpCloseButton">&Close</String>  
  18.   <String Id="InstallAcceptCheckbox">I &agree to the license terms and conditions</String>  
  19.   <String Id="InstallOptionsButton">&Options</String>  
  20.   <String Id="InstallInstallButton">&Install</String>  
  21.   <String Id="InstallCloseButton">&Close</String>  
  22.   <String Id="OptionsHeader">Setup Options</String>  
  23.   <String Id="OptionsLocationLabel">Install location (disk root path is not recommanded):</String>  
  24.   <String Id="OptionsBrowseButton">&Browse</String>  
  25.   <String Id="OptionsOkButton">&OK</String>  
  26.   <String Id="OptionsCancelButton">&Cancel</String>  
  27.   <String Id="ProgressHeader">Setup Progress</String>  
  28.   <String Id="ProgressLabel">Processing:</String>  
  29.   <String Id="OverallProgressPackageText">Initializing...</String>  
  30.   <String Id="ProgressCancelButton">&Cancel</String>  
  31.   <String Id="ModifyHeader">Modify Setup</String>  
  32.   <String Id="ModifyRepairButton">&Repair</String>  
  33.   <String Id="ModifyUninstallButton">&Uninstall</String>  
  34.   <String Id="ModifyCloseButton">&Close</String>  
  35.   <String Id="SuccessHeader">Setup Successful</String>  
  36.   <String Id="SuccessLaunchButton">&Launch</String>  
  37.   <String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>  
  38.   <String Id="SuccessRestartButton">&Restart</String>  
  39.   <String Id="SuccessCloseButton">&Close</String>  
  40.   <String Id="FailureHeader">Setup Failed</String>  
  41.   <String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the <a href="#">log file</a>.</String>  
  42.   <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>  
  43.   <String Id="FailureRestartButton">&Restart</String>  
  44.   <String Id="FailureCloseButton">&Close</String>  
  45. </WixLocalization>  

        我们只需要修改每个String节点中的内容,就可以达到本地化安装内容的目的。


自定义安装序列


        上面我们已经将安装界面全部自定义完毕,脸面上的事情总算是做完了,我们要解决的根本问题还在眼前,如何自定义调整安装顺序?答案就是通过Chain节点 来完成。Chain节点定义了打包安装的顺序,默认是从上到下逐个完成,当然你也可以在子节点中通过After属性来调整安装顺序。


        首先是判断并安装.NET Framework 4.0环境。

 

[html] view plain copy
  1. <ExePackage Id="Netfx4Full"  
  2.     Cache="no"  
  3.     Compressed="no"  
  4.     PerMachine="yes"  
  5.     Permanent="yes"  
  6.     Vital="yes" InstallCommand=" /q /norestart"  
  7.     SourceFile="dotNetFx40_Full_x86_x64.exe"  
  8.     DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=164193"  
  9.     DetectCondition="DotNetFramework40FullInstallRegValue=1" />  

        我们知道,从网上下载得到的.NET 4.0是一个exe安装包,因此我们要用ExePackage进行声明。

        Compressed表示是否要将该安装包打包在bootstrapper.exe文件中,我们回忆一下上一讲,上一讲我们的Setup1.msi文件因 为没有带上该属性,就自动将安装包打包在bootstrapper中了,因此我们只得到了一个安装文件。如果Compressed="no",那就会在bootstrapper.exe边上出现另外一个单独的安装文件,这样可以减小我们发布的尺寸。

        PerMachine是表示是否要采用UAC权限进行安装,因为有些安装文件需要以管理员身份运行才能安装成功,而我们现在采取的是静默安装策略,因此需要在定义安装的时候就表明是否需要UAC权限。

        Permanent表示卸载时是否需要同时卸载该安装包。yes表示卸载产品时该安装包不需要同时卸载,将会永远留在客户的计算机里面。

        Vital表示是否该安装时必须的,如果该安装是必须的,那如果该安装没有成功,后续的所有安装都不会进行。

        InstallCommand是在安装时需要跟上的参数,我们知道.NET的静默安装需要带上“ /q /norestart”参数,这样我们用bootstrapper托管下就可以让.NET静默安装完毕了。

        SourceFile表明安装文件的名称是什么,它和DownloadUrl是任选的,也就是说如果安装时发现该文件包不存在的话,需要从什么URL进行自动下载并安装。

        DetectCondition是bootstrapper的精髓,它用一个表达式来判断一台计算机上该包是否已经安装 过,DotNetFramework40FullInstallRegValue和文档最后的util:RegistrySearch节点ID是一致的,util:RegistrySearch代表查看注册表中的某个表项的值的变量,然后匹配该注册表项值满足条件,则说明已经安装,如果不满足则说明需要安装。


 

[html] view plain copy
  1. <MsiPackage Compressed="no" SourceFile="SSCERuntime-CHS.msi" Vital="yes" DisplayInternalUI="no" Permanent="yes" ForcePerMachine="yes"  
  2.           DownloadUrl="http://go.microsoft.com/fwlink/?LinkID=166085"  
  3.           InstallCondition="VersionNT = v5.1" />  


        MsiPackage节点上一讲已经使用过,如果要安装MSI文件必须用这个节点,它的属性和ExePackage大同小 异,DisplayInternalUI表示是否要静默安装,ForcePerMachine代表需要UAC权限。InstallCondition代表 需要安装的判定条件,请注意,这个和上面的DetectCondition是反的,上面是如果判定为false则安装,这个是判定为true则安装。(看 到这儿实在觉得这是不是两个人写的框架啊,属性名称也不统一,连判定安装条件也要反一反,很是反人类 啊!)InstallCondition="VersionNT = v5.1"表示如果是XP则进行安装,VersionNT是框架自带的变量,可以在WiX的网站中查询并得到其他的变量使用方法。


 

[html] view plain copy
  1. <MsiPackage Compressed="no" SourceFile="IntSig.CamCard.Installer.msi" Vital="yes" DisplayInternalUI="no" Permanent="no"  ForcePerMachine="yes">  
  2.   <MsiProperty Name="TARGETDIR" Value="[InstallFolder]"/>  
  3. </MsiPackage>  

        最后一个MSI就是我们自己定义的MSI了,前面是把环境安装包给安装掉,最后就是安装我们自己的产品包。重点需要解释的 是<MsiProperty Name="TARGETDIR" Value="[InstallFolder]"/>节点,这个其实就是相当于我们使用msiexec.exe系统命令进行MSI安装,如果我们要 把MSI静默安装,又必须指定要装到某个目录下,需要使用msiexec.exe ***.msi TARGETDIR="C:\AA\" 这样的命令格式,其实上面的 MsiProperty属性就是把之前在bootstrapper启动界面选项中选中的安装目录路径通过变量传送了过来。


        完成上面的这些工作,再把所需要的安装包,配置文件都放到工程里面后,经过项目生成,我们就拿到很完美的bootstrapper了。现在的结果是,最极 限情况下我们只需要发布一个bootstrapper,后续所有的软件依赖就能下载并安装,极大得减少了用户下载安装的负担。并且因为可以动态判断依赖 包,所以用户的安装速度也得到极大的提升。最最重要的是,只需要在安装第一个包的时候进行一次UAC询问,后续就不再会有类似的恼人确认对话框了。至此, 我们之前所有提出的VS打包项目的不足就全部解决了。

你可能感兴趣的:(bootstrap)