您的位置:首页 > 其它

.Net部署二三事之一——如何为VS安装文件MSI制作更新补丁MSP

2008-10-19 12:29 1166 查看
前言


首先需要说明的是,本文使用的工具是
VS IDE

Orca.exe
,所以
InstallShield

Wise
等其它打包工具不在讨论范围,另外需要
InstallShield

Wise
关于制作安装文件和更新补丁比
VS
IDE

Orca.exe
更复杂。

其次本文的背景是,笔者发现国内关于如何在
VS IDE Setup Project
(安装和部署工程)制作的
MSI
基础上制作
MSP
更新补丁的文章少之又少,所以再查询了众多英文文章后,总结了如下经验,大部分内容可能只是 http://www.codeproject.com/KB/install/dotnetpatching.aspx?fid=209224&fr=51&df=90&mpp=25&noise=3&sort=Position&view=Quick#xx0xx

How to create
installation patches for VS.NET deployment projects
一文的翻译。(如果英文好的朋友可以直接看上文,但笔者也有一些解决按照上文步骤制作
MSP
遇到问题的经验共享)

准备


1、

首先需要下载
Microsoft Platform SDK
,地址:
http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en



2、

下载后,安装
Orca.Msi

Orca
其实是一个
Microsoft
用于编辑配置
MSI

MSP
以及打开制作
MSP
必须的
PCP
文件的工具),在
Microsoft Platform SDK
的安装目录下,
C:/Program Files/Microsoft Platform SDK/Bin/



3、

其次,需要有升级前的
MSI
安装文件,以及对应的
VS
的安装部署工程;(注意
codeproject
中一文所有准备文件都放在安装部署工程所在目录,否则套用它提供的
Patch.cmd
将会出错,其实完全不用在安装部署目录下,可以另行建立一个工作目录,但如果读者一开始不熟悉
Orca
工具的情况下,还是按照
codeproject
中一文来设置工作目录,切记所有的目录都不宜太长,最好没有特殊字符和空格。)

4、

在工作目录中,需要有如下子目录:
TargetImage

UpgradedImage

TargetImage
用于存放升级前的
MSI
安装文件,
UpgradedImage
用于存放升级后的
MSI
安装文件;(如果没有生成升级后的安装文件,先不执行该步。)这里需要注意,提醒按照
codeproject
制作
MSP
的读者,由于它在文中用到的
Patch.cmd
与本文有所不用,因此按照
codeproject
制作
MSP
的读者需要建立不用的目录结构,这里就不再赘述。

5、

需要有一些安装文件制作的基本知识,如主版本号:
MajorVersion
,次版本号,
ProductCode

UpgradeCode
等等。

制作步骤


1、


C:/Program Files/Microsoft
Platform SDK/Samples/SysMgmt/Msi/Patchi

ng/

Template.pcp

拷贝到工作目录下,并重新命名为
patch.pcp

;(名字可自定义,但注意在

Patch.cmd

中相应修正)

2、

利用

Orca

打开

patch.pcp

,为

ImageFamilies

表添加一行记录,

Family

字段需赋值,可以自定义,该值表示产品所在家族系列加上主版本号,例如

ESRI

将该值赋为

ArcGIS92



3、


PatchSequence
表添加一行记录,
PatchFamily
设为上表中
Family

的值(也可以不同),

Sequence
字段为
1.0.0
(所有
pcp
表中字段设置可参考 http://msdn.microsoft.com/en-us/library/aa370890(VS.85).aspx );

4、

修改
Properties
表中记录,
PatchGUID
右键后选取粘贴生成一个新的
GUID
(非常重要,每次制作
MSP
都需要重新生成,笔者犯过类似错误,花了半天时间才找到原因),
PatchOutputPath
设置需要导出的地址,可设置为
Patch/Patch.msp
,注意这是相对目录,相对于
patch.pcp

文件,另外为该表添加一记录,

Name



MinimumRequiredMsiVersion



Value



200



5、



TargetImages
表添加一记录,
Target
:可自定义(推荐为
Family
值加上升级前次版本号,如
ArcGIS92MSI1
,原因是此表可添加多条记录,以后应用将多个不同的目标版本升级到最新版本,后面将详述,该段在
codeproject
中未提到,属于高级应用),
MsiPath

TargetImage/setup.msi
(相对目录,注意
setup.msi
不用改为读者的
msi
文件名,因为在
Patch.cmd
中将读者的
msi
拷贝为
setup.msi
,可细读
Patch.cmd
),
Upgraded
:与下面
UpgradeImages
表中该值对应,(推荐为
Family
值加上升级后的次版本号,如
ArcGIS92MSI2
),
Order

1
(多条记录时需要有大小顺序,后面详述),
IgnoreMissingSrcFiles

0


6、


UpgradeImages
表添加一记录,
Upgraded
:与上表中该值对应,
MsiPath

UpgradedImage/setup.msi
(相对目录,此处不用改,细读
Patch.cmd
),
Family
:与
ImageFamlies
表中该值对应。

7、

创建
Patch.cmd
文件,(按照
codeproject
一文的读者参考它的
Patch.cmd
文件)

@SETLOCAL

@set path=%path%;"C:/Program Files/Microsoft Platform
SDK/Samples/SysMgmt/Msi/Patching"

@set PatchTmp=C:/Tmp1

:ok

rmdir /s /q %PatchTmp%

mkdir C:/Tmp1

mkdir C:/Tmp1/TargetImage

mkdir C:/Tmp1/UpgradedImage

mkdir C:/Tmp1/Patch

for %%a in ("TargetImage/*.msi") do copy "%%a"
C:/Tmp1/setup.msi

msiexec /qb /a C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/TargetImage/ /L*v
C:/Tmp1/TargetImage/setup.log

del
C:/Tmp1/setup.msi

for %%a in ("UpgradedImage/*.msi") do copy "%%a"
C:/Tmp1/setup.msi

msiexec /qb /a C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/UpgradedImage
/L*v C:/Tmp1/UpgradedImage/setup.log

del
C:/Tmp1/setup.msi

copy patch.pcp C:/Tmp1

set PatchDir=%CD%

C:

cd Tmp1

msimsp -s patch.pcp -p Patch/patch.msp -l Patch/patch.log -f
C:/Tmp1/Tmp -d

rmdir /s /q C:/Tmp1/TargetImage

rmdir /s /q C:/Tmp1/UpgradedImage

rmdir /s /q C:/Tmp1/Tmp

F:

cd %PatchDir%

mkdir Patch

mkdir Patch/%1

copy C:/Tmp1/Patch/*.* Patch/%1/*.*

rmdir /s /q C:/Tmp1

:end

Pause

注意,定位到
F
:该行,改为读者工作目录所在盘符,切记。

8、

生成升级后的安装文件
MSI
,修改
VS
安装部署工程属性
Version
,(如升级前为
1.0.0
,升级后可改为
1.0.1
,注意改次版本号,关于主版本号和次版本号的升级请参阅
MSDN
,也可见下文。)此时,系统提示是否自动修改
ProductCode

UpgradedCode
,注意此处非常关键,一定要记住选
NO
。具体为什么,有一定
ProductCode

UpgradedCode
知识的读者肯定了解此处的意义,
UpgradedCode
每个产品家族为同一个,
ProductCode
只有在主版本号升级时,才需要修改,而
MSP
一般为最小版本号升级所使用,所以,一句话,不要改。(改了,如果有问题,笔者解决不了)

9、

将生成的
MSI
拷贝到工作目录的
UpgradedImage
下,按照
codeproject
一文的读者不用执行该步,因为它文中的
Patch.cmd
将自动读取
Debug
目录下的
MSI
,这就是它文中必须要求读者将所有文件拷贝到安装部署工程目录下的原因。

10、

该步不用执行,每当用户
Build
安装部署工程时,系统会自动更新
PackageCode
,这里如修改
PackageCode
,可使用
Orca
打开
MSI
,在查看菜单下摘要信息中修改。

11、

终于到最后一步,运行
Patch.cmd
,如前后改动不大、并且打包文件较少时,执行时间非常短,如果是改动较大,就稍等几分钟,抽根烟,喝杯咖啡。提醒:在
Properties
表中的
IncludeWholeFilesOnly
字段用于判定当打包文件不同时,提取增量,还是直接采取整个新文件,前者可使得
MSP
瘦身,但
MSP
执行时间较长,后者相反。

关于
PatchCMD



1、

首先设置环境变量
Path
以及临时目录;

2、

如临时目前存在先删除,然后建立目录格式;

3、

拷贝升级前
MSI
到临时目录,并利用
MSIExec
解压;注意:
TARGETDIR=C:/Tmp1/TargetImage/
,一定不要与拷贝后的
MSI
相同目录,因为
MSI
解压后还会生成一个较小的文件名相同的
MSI
,这样会导致
MSIExec
解压出错;(笔者被这步给整得很惨)

4、

拷贝升级后
MSI
到临时目录,并利用
MSIExec
解压;

5、

拷贝
PCP
文件到临时目录,利用
msimsp
生成
MSP


6、

将生成
MSP
拷回工作目录,删除临时目录。

关于主版本号、次版本号、最小版本号(当版本格式为
1.0.0
时,个人意见如下):


1、

当程序只是局部更新,改动较小,修正少量
Bug
,可选择发布
MSP
,修改最小版本号,
ProductCode
不变;

2、

当程序更新大量模块的代码,做了较大改动和调整,但结构保持不变,可修改第二位版本号,
ProductCode
改变,重新发布
MSI


3、

当程序的架构发生变化,如从面向过程改动到面向对象全组件式架构,修改主版本号,
ProductCode
改变,重新发布
MSI


关于多个不同的目标版本升级到最新版本:



TargetImages
中一条记录就对应一个目标版本升级到最新版本,例如
1.0.0

1.0.2

1.0.1

1.0.2
,这样建立的
MSP
可适用与将
1.0.0

1.0.1
升级到
1.0.2
,如果只有
1.0.1

1.0.2
,就无法将
1.0.0
升级到
1.0.2
。对应的
Patch.cmd
和工作目录结构只需做略微改动即可达到目的。以下
Patch.cmd
可供参考:

@SETLOCAL

@set
path=%path%;"C:/Program Files/Microsoft Platform
SDK/Samples/SysMgmt/Msi/Patching"

@set
PatchTmp=C:/Tmp1

:ok

rmdir /s /q
%PatchTmp%

mkdir C:/Tmp1

mkdir
C:/Tmp1/TargetImage

mkdir
C:/Tmp1/TargetImage/1

mkdir
C:/Tmp1/TargetImage/2

mkdir
C:/Tmp1/TargetImage/3

mkdir
C:/Tmp1/UpgradedImage

mkdir
C:/Tmp1/Patch

for %%a in
("TargetImage/1/*.msi") do copy "%%a" C:/Tmp1/setup.msi

msiexec /qb /a
C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/TargetImage/1 /L*v
C:/Tmp1/TargetImage/setup.log

del

C:/Tmp1/setup.msi

for %%a in
("TargetImage/2/*.msi") do copy "%%a" C:/Tmp1/setup.msi

msiexec /qb /a
C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/TargetImage/2 /L*v
C:/Tmp1/TargetImage/setup.log

del

C:/Tmp1/setup.msi

for %%a in
("TargetImage/3/*.msi") do copy "%%a" C:/Tmp1/setup.msi

msiexec /qb /a
C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/TargetImage/3 /L*v
C:/Tmp1/TargetImage/setup.log

del

C:/Tmp1/setup.msi

for %%a in
("UpgradedImage/*.msi") do copy "%%a" C:/Tmp1/setup.msi

msiexec /qb /a
C:/Tmp1/setup.msi TARGETDIR=C:/Tmp1/UpgradedImage /L*v
C:/Tmp1/UpgradedImage/setup.log

del

C:/Tmp1/setup.msi

copy
patch4.pcp C:/Tmp1

set
PatchDir=%CD%

C:

cd Tmp1

msimsp -s
patch4.pcp -p Patch/patch4.msp -l Patch/patch4.log -f C:/Tmp1/Tmp -d

rmdir /s /q
C:/Tmp1/TargetImage/1

rmdir /s /q
C:/Tmp1/TargetImage/2

rmdir /s /q
C:/Tmp1/TargetImage/3

rmdir /s /q
C:/Tmp1/TargetImage

rmdir /s /q
C:/Tmp1/UpgradedImage

rmdir /s /q
C:/Tmp1/Tmp

F:

cd %PatchDir%

mkdir Patch

mkdir Patch/%1

copy
C:/Tmp1/Patch/*.* Patch/%1/*.*

rmdir /s /q
C:/Tmp1

:end

pause

参考链接:


1、

http://www.codeproject.com/KB/install/dotnetpatching.aspx?fid=209224&fr=1&df=90&mpp=25&noise=3&sort=Position&view=Quick#xx0xx

2、

http://msdn.microsoft.com/en-us/library/aa367816(VS.85).aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: