在软件部署和分发过程中,MSI安装包是一种常见的安装方式。当需要更新已安装的MSI包时,通常会面临一个问题:如果新的安装包版本号与已安装的版本相同,安装程序会提示用户先卸载旧版本。为了解决这个问题,需要手动修改安装包的版本号和产品代码。本文将介绍一种使用VBScript自动化执行这一过程的方法。
MSI安装包在更新时,如果新旧版本号相同,安装程序会报错,提示需要先卸载旧版本。虽然Visual Studio的安装项目中有一个“RemovePreviousVersions”属性,但仅仅将其设置为True并不能解决问题。实际上,还需要更新版本号和产品代码。这是一个手动过程,但可以通过编写一个简单的脚本来自动化完成。
这个脚本是用VBScript编写的,其主要任务包括:
脚本使用了正则表达式来查找需要修改的项目并进行替换。正则表达式的Execute方法用于查找当前的版本号条目,可以从结果的Matches集合中提取。版本号由三部分组成,以点号分隔。对于本例,只递增版本号的最后一部分。
正则表达式的Replace方法用于查找并修改内容。在VBScript中创建新的GUID也很有趣:
VBScript
guid = CreateObject("Scriptlet.TypeLib").Guid
guid = Left(guid, Len(guid) - 2)
目前还不清楚为什么GUID后面会有两个字节的垃圾数据,但去掉它们就可以了。
以下是完整的脚本示例:
VBScript
' Increment the version number of an MSI setup project
' and update relevant GUIDs
'
' Hans-Jürgen Schmidt / 19.12.2007
'
Set a = WScript.Arguments
If a.Count = 0 Then
WScript.Quit 1
'
' Read and backup project file
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(a(0))
s = f.ReadAll
f.Close
fbak = a(0) & ".bak"
If fso.FileExists(fbak) Then
fso.DeleteFile fbak
fso.MoveFile a(0), fbak
'
' Find, increment and replace version number
Set re = New RegExp
re.Global = True
re.Pattern = "(""ProductVersion"" = ""8:)(\d+(\.\d+)+)"
Set m = re.Execute(s)
v = m(0).SubMatches(1)
v1 = Split(v, ".")
v1(UBound(v1)) = v1(UBound(v1)) + 1
vnew = Join(v1, ".")
'
' MsgBox v & " --> " & vnew
s = re.Replace(s, "$1" & vnew & "")
'
' Replace ProductCode
re.Pattern = "(""ProductCode"" = ""8:)(\{.+\})"
guid = CreateObject("Scriptlet.TypeLib").Guid
guid = Left(guid, Len(guid) - 2)
s = re.Replace(s, "$1" & guid & "")
'
' Replace PackageCode
re.Pattern = "(""PackageCode"" = ""8:)(\{.+\})"
guid = CreateObject("Scriptlet.TypeLib").Guid
guid = Left(guid, Len(guid) - 2)
s = re.Replace(s, "$1" & guid & "")
'
' Write project file
fnew = a(0)
Set f = fso.CreateTextfile(fnew, True)
f.Write(s)
f.Close
这个脚本简单易用(除了正则表达式,总是需要查找语法...)。
要将此脚本用于构建过程,只需将其放入搜索路径中的任何目录。然后,在安装项目中添加一个PreBuildEvent,例如:
NewSetupVersion.vbs "$(ProjectDir)Setup.vdproj"
上述VBScript脚本对于MSI安装项目非常有帮助。也许它对其他人也有用。