Wix打包系列(一)如何使用wix制作安装程序
最近由于项目需要,需要给客户制作安装程序,一开始使用vs2005自带的打包工程来打包,但用了一段时间发现vs打包太死板,而且使用起来问题很多。收费的商业打包工具不在我考虑范围内,于是在网上找到了wix,稍微了解了下,发现wix的确可以满足我的需求;但是网上wix中文的资料少的可怜,百度,google上搜索到关于wix中文的资料少的可怜,有的只是一些简单的应用,还不足以满足我的要求;没办法,只能靠自己了,还好项目不是很急,于是开始花时间慢慢熟悉wix了。一路熟悉下来,发现使用wix也是个不小的工程,因此我将我使用wix过程的一些主要的问题都记录下来,供以后自己和大家参考:
1.1 安装wix
首先,我们需要到网上下载一个wix安装文件,下载地址:http://wix.sourceforge.net/ ,这里我们下载的版本是WiX v3.0 released,以下所有示例程序都是运行在这个版本下的。
wix是用C#写的,安装wix之前,必须安装.NET Framework 2.0 和
Service Pack 1 ,这是wix 工具集运行环境必须的,但并不意味着安装应用程序的机器上就一定需要使用Net Framework运行环境,这取决于你的应用程序使用的开发语言环境。使用wix不尽可以打包.net应用程序,也可以打包java应用程序和其他语言开发的应用程序。
在开始使用wix之前,我们需要先下载示例源码,这些示例都来自WiX
tutorial,里面每个示例在WiX tutorial中都有详细说明,E文好的可以先看看;大家会发现WiX tutorial中有些地方比较难理解,可能是因为里面涉及到一些msi sdk的知识,文中并没有详细说明,我也是刚接触wix和msi不久,文中对有些概念可能会有理解不准确的地方。该文都是我学习和使用wix的经验,考虑到wix初学者,刚开始会尽量介绍的详细些。
1.2 wix简介
wix是微软Windows Installer XML的缩写,WiX 的源代码是使用 XML 文件编写的,然后经过预处理、编译与链接,以创建 Windows Installer 数据库。我们可以在命令行上使用 WiX 工具集或使用 MSBuild,来编译与链接 WiX 源代码,而且如果我们安装wix之前已经安装了了Visual Studio(vs2005或者vs2008,据说vs2010已经集成了wix3.0),则还可以在Visual Studio IDE环境中生成安装项目。
这里我们主要讨论命令行方式使用wix工具集,在第七章会提到如何使用在vs环境下使用wix;wix最常用的两个命令就是candle和light, candle是用来编译wix源文件的,light是用来链接编译后的中间文件生成msi安装包。为了了解他们的作用,我们看看wix怎么生成安装包的。
1.3 生成Samplefirst示例安装包
我们先来了解他们的用法,在示例源码中找到SampleFirst,用vs或者其他文本编辑器打开SampleFirst.wxs,将其中的每个YOURGUID-XXXX-XXXX-XXXX-XXXXXXXXXXXX 替换成唯一的GUID标识,我们可以使用vs自带的GUID生成器,在vs工具菜单下选择创建GUID,必须确保每个GUID都是唯一的(注意这里可以GUID既可以是带大括号的,也可以不带大括号)。接着我们可以编译了,编译之前最好将C:/Program
Files/Windows Installer XML v3/bin目录设置到系统的环境变量path中,这样我们在任何目录下都可以执行命令了,在命令提示符下,我们执行以下命令进行编译:
candle.exe Samplefirst.wxs
执行成功后会在当前目录下生成SampleFirst.wixobj文件,接着我们执行light命令:
light.exe Samplefirst.wixobj
light命令执行成功后我们就可以看到生成的安装文件SampleFirst.msi,这样一个简单的msi安装包就制作成功了。
1.4 SampleFirst代码
SampleFirst示例展示了最基本的wix应用,如果想要生成功能更丰富的安装包,还必须知道如何编写wix代码;wix源代码是标准的xml标记语言,我们打开SampleFirst.wxs文件,来看看代码的构成:
<Product>标签是我们发布的产品的基本信息,Language和 Codepage是设置我们生成安装包的语言环境,以后章节我们会详细讲到本地化语言的配置;Name和Manufacturer很好理解;需要注意的是Id和UpgradeCode属性,他们是具有唯一标识的GUID编号,还有Version属性是发布产品的版本号(不包括修订版本号)。
另外<Package>标签的ID也是具有唯一标识的GUID编号,所不同的是对于每次生成的安装包,我们都需要一个不同GUID,因此这里设置成*号,每次编译时时候编译器会自动为它生成一个GUID,关于这几个属性的作用我们将在制作升级程序和更新包的时候详细讲解。Description属性是安装包的全名或者叫描述;Comments可以理解成是注解,它是可选的;InstallerVersion则是指定运行该安装包所需要的Windows
Installer的最低版本;Compressed指定是否压缩安装包中的文件,一般我们都设置成yes,可以节省不少空间。
Directory。
)下生成一个自定义的目录,目录名是Name属性的值;
会在启动时设置它的值;同样,Windows Installer 也会设置INSTALLDIR的值,也可以在其他地方引用它,即使你没有显式定义一个INSTALLDIR
Property。(关于Windows Installer 提供的属性列表,可以在msi sdk document中查到,参考Property Reference;从其中我们可以看到下面的ProgramMenuFolder和DesktopFolder都是Windows
Installer 已经提供的属性。)
另外这里Directory的默认的INSTALLDIR值是根据目录结构自动计算出来的,如果我们要将某些文件安装在固定位置,比如E盘根目录下,则我们需要在显式定义一个Property ,Property 的Value属性就是要存放目录的位置。大家可以尝试一下在Fragment下添加如下代码,会出现什么效果:
<Property Id ="INSTALLDIR" Value="E:/"/>
Directory中定义了安装在开始菜单->程序中的快捷方式。
。
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Name='Foobar 1.0' Id='{2C9A3180-95F0-4cdd-B02C-A0ABCAAE3413}' UpgradeCode='{F4F8195E-E907-42dd-BB90-CC2403FA7384}'
Language='1033' Codepage='1252' Version='$(var.Version)' Manufacturer='Acme Ltd.'>
<Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />
<Icon Id="Foobar10.exe" SourceFile="$(var.Version)/FoobarAppl10.exe" />
<Icon Id="word.ico" SourceFile="$(var.Version)/word.ico" />
<Feature Id='Complete' Title='Foobar 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR'>
<Feature Id='MainProgram' Title='Program' Description='The main executable.' Level='1'>
<ComponentGroupRef Id='MainCompGroup' />
<ComponentRef Id='compHelperLibrary' />
</Feature>
<Feature Id='Documentation' Title='Description' Description='The instruction manual.' Level='1000'>
<ComponentRef Id='compManual' />
</Feature>
</Feature>
</Product>
<Fragment>
<ComponentGroup Id ="MainCompGroup">
<Component Id='compMainExecutable' Guid='{0008EE68-EA36-4d5d-8BC5-713029E1909A}' Directory='INSTALLDIR'>
<File Id='filFoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='$(var.Version)/FoobarAppl10.exe' KeyPath='yes'>
<Shortcut Id="startmenuFoobar10" Directory="ProgramMenuDir" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
<Shortcut Id="desktopFoobar10" Directory="DesktopFolder" Name="Foobar 1.0" WorkingDirectory='INSTALLDIR' Icon="Foobar10.exe" IconIndex="0" Advertise="yes" />
</File>
</Component>
<Component Id="compProgramMenuDir" Guid="{6886685C-E1B1-48d9-B6A7-548175BD8F17}" Directory="ProgramMenuDir">
<Shortcut Id="UninstallProduct" Name="Uninstall My Application" Directory="ProgramMenuDir" Target="[SystemFolder]msiexec.exe" Arguments="/x [ProductCode]" Description="Uninstall"/>
<RemoveFolder Id='rmvProgramMenuDir' On='uninstall' />
<RegistryValue Root='HKCU' Key='Software/[Manufacturer]/[ProductName]' Type='string' Value='' KeyPath='yes' />
</Component>
</ComponentGroup>
<ComponentGroup Id='ExtraGroup'>
<Component Id='compHelperLibrary' Guid='{A30DAC3F-2902-479c-B530-B90A7BA8E514}' Directory='INSTALLDIR'>
<File Id='filHelperDLL' Name='Helper.dll' DiskId='1' Source='$(var.Version)/Helper.dll' KeyPath='yes' />
</Component>
<Component Id='compManual' Guid='{25518565-2E48-415c-B4FD-A20E2EA869D5}' Directory='INSTALLDIR'>
<File Id='filManual' Name='Manual.pdf' DiskId='1' Source='$(var.Version)/Manual.pdf' KeyPath='yes'>
<Shortcut Id="startmenuManual" Directory="ProgramMenuDir" Name="Instruction Manual" Icon="word.ico" Advertise="yes" />
</File>
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='ManufacturerDir' Name='Acme'>
<Directory Id='INSTALLDIR' Name='Foobar 1.0'>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="ProgramMenuDir" Name="Foobar 1.0">
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
</Directory>
</Fragment>
</Wix>
Shortcut,因此Component的KeyPath可以是FILE;
作为KeyPath,因为对于UninstallProduct
Shortcut来说,因为指定了Target属性,所以他是一个non-advertised Shortcut,必须使用注册表键作为KeyPath;
Icon 使用的是执行文件的Icon,我们在Shortcut中使用IconIndex
指定Icon;另一个Icon是文件Icon,我们可以复制一个word.ico到我们打包目录下,在Shortcut中只需指定Icon的标识符就可以了。
我们在编译源代码之前,先新建一个版本目录1.0.0,所有要安装的文件均放在该目录下,该版本的安装包也会生成到该目录,将前面我给的代码复制到编辑器中,保存到该目录下Sample.wxs文件中;源代码中FILE和Icon 中的Source属性就是源文件的路径,这里我们都使用的相对路径。
所有准备工作都已经做完了,在Sample.wxs 所在的目录执行candle命令进行编译,将Version属性传给编译器:
candle.exe -dVersion=1.0.0 Sample.wxs -out 1.0.0/
light.exe -out 1.0.0/Sample.msi 1.0.0/Sample.wixobj
Wix打包系列(一)如何使用wix制作安装程序的更多相关文章
- Wix打包系列 (六)制作升级和补丁包
原文:Wix打包系列 (六)制作升级和补丁包 前面我们已经知道怎么制作一个完整安装包了,但我们的软件往往不能一次性就满足客户的需要,当客户需要我们给软件进行升级的时候,我们应该怎么做呢? 在这之前,我 ...
- Wix打包系列(七) 添加系统必备组件的安装程序
原文:Wix打包系列(七) 添加系统必备组件的安装程序 我们知道在vs的打包工程中添加系统必备组件是一件很容易的事情,那么在wix中如何检测系统必备组件并在安装过程中安装这些组件.这里以.Net Fr ...
- Wix打包系列(五) 部署数据库
原文:Wix打包系列(五) 部署数据库 很多人在使用vs进行打包的时候,经常会为数据库部署的问题犯愁,即便是重写Installer类的方法,也不是很可靠方便,下面我们来看看在wix中如何部署数据库. ...
- Wix打包系列(四) 自定义UI
原文:Wix打包系列(四) 自定义UI 除了标准的安装界面,如果我们要在安装时需要提供一些额外的信息时,这时就需要自定义界面来显示和录入这些信息. 4.1 自定义对话框 如上一章中我们测试数据库的连 ...
- Wix打包系列(三)自定义Action(Custom Action)
原文:Wix打包系列(三)自定义Action(Custom Action) 3.1 关于Action 我们已经知道如何生成具有标准安装界面的安装程序了,Windows Installer按照我们的界面 ...
- Wix打包系列(二)用户界面和本地化操作
原文:Wix打包系列(二)用户界面和本地化操作 上一章节,我们已经大概知道如何对文件进行打包安装,不过我们也注意到,通过对Sample.wxs的编译链接,生成的msi安装包没有任何用户界面,只有一个安 ...
- 使用好压(HaoZip)软件打包EverEdit制作安装程序
最近使用EverEdit,使用原始的安装程序安装后,需要重新安装插件,对配置文件进行了修改,定制了工具栏.将安装后的程序目录进行打包,制作新的安装包,便于携带. 以下为打包制作过程: 打包原料:Eve ...
- Unity 制作安装程序和卸载程序
1.最简单的方式通过winrar制作 但是做出来的页面好low的感觉 参考链接:https://www.cnblogs.com/fetty/p/5185913.html 2.通过inno制作安装程序: ...
- vs.net应用程序图标以及制作安装程序快捷方式图标设置
我们通常在开发软件完毕后需要打包制作安装程序,这个时侯一般都会需要设置应用程序的图标,使用默认的图标一般都比较难看,那么我们应该怎样设置自定义的图标呢? 我现在要讲的图标设置有两种情况, ...
随机推荐
- Servlet的学习(四)
在本篇的Servlet的学习中,主要来学习由使用MyEclipse来开发Servlet的一些小细节. 细节一:在web.xml中可以对同一个Servlet配置多个对外访问路径,并如果在web.xml中 ...
- DBA 应该要注意Linux 环境下的一些操作
DBA 对OS的依赖.一丁点儿也不亚于DB.对于Oracle DBA.尤为突出 DB和OS的感情也与日俱增.耦合度高的让人一度以为这两要劳燕双飞了 例如.Oracle里面. 而且.故障诊断以及 ...
- Codeforces Round #306 (Div. 2) D.E. 解题报告
D题:Regular Bridge 乱搞. 构造 这题乱搞一下即可了.构造一个有桥并且每一个点的度数都为k的无向图. 方法非常多.也不好叙述.. 代码例如以下: #include <cstdio ...
- 【ASP.NET Web API教程】1 ASP.NET Web API入门
原文 [ASP.NET Web API教程]1 ASP.NET Web API入门 Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 ...
- Android 高手进阶,自己定义圆形进度条
背景介绍 在Android 开发中,我们常常遇到各种各样绚丽的控件,所以,依靠我们Android本身所带的控件是远远不够的,许多时候须要我们自定义控件,在开发的过程中.我们公司遇到了一种须要自己写的一 ...
- Codeforces 39E What Has Dirichlet Got to Do with That? 游戏+内存搜索
主题链接:点击打开链接 意甲冠军: 特定 a一箱 b球 不变n (球和箱子都不尽相同,样的物品) 设 way = 把b个球放到a个箱子中的方法数, 若way >= n则游戏结束 有2个人玩游戏. ...
- Qt之设置QWidget背景色(QStyleOption->drawPrimitive(QStyle::PE_Widget)方法比较有趣)
QWidget是所有用户界面对象的基类,这意味着可以用同样的方法为其它子类控件改变背景颜色. Qt中窗口背景的设置,下面介绍三种方法. 1.使用QPalette2.使用Style Sheet3.绘图事 ...
- 内网穿透神器ngrok(转)
相信做Web开发的同学们,经常会遇到需要将本地部署的Web应用能够让公网环境直接访问到的情况,例如微信应用调试.支付宝接口调试等.这个时候,一个叫ngrok的神器可能会帮到你,它提供了一个能够在公网安 ...
- 理想非常丰满,现实非常骨感——致WiFi通话
WiFi通话一词,近来火热,国外,iOS 8系统測试版新增WiFi通话功能,英国运营商也着手WiFi免费通话,国内也没落下,阿里发布的170资费方案中就包含WiFi免费通话. 近日,据外媒报道,在美国 ...
- mybatis 的简单使用
须要用到的包:(这里仅仅是当中一个版本号.其它的百度) mysql-connector-java-5.1.6-bin mybatis-3.2.2 先看项目文件夹: 配置文件mybatisconfig. ...