我正在通过编辑 MSI 数据库更改 MSI 的产品代码、升级代码和产品名称。
参考:- http://www.codeproject.com/Articles/383481/Editing-an-MSI-Database
我可以更改上述所有参数,但无法更改 Package Code。
建议一种更改包代码的方法。
我正在通过编辑 MSI 数据库更改 MSI 的产品代码、升级代码和产品名称。
参考:- http://www.codeproject.com/Articles/383481/Editing-an-MSI-Database
我可以更改上述所有参数,但无法更改 Package Code。
建议一种更改包代码的方法。
出于好奇,找到了一种使用 vbscript 的方法:“属性 #9 ”是包代码(修订号)。
Set wi = CreateObject("WindowsInstaller.Installer")
Set summary = wi.SummaryInformation("your.msi", 2)
summary.Property(9) = "{PUT-NEW-GUID-HERE}"
summary.Persist
我猜这里的要求是多次安装相同的 MSI,这意味着他们需要更改那组 guid。然而,解决该问题的更正常方法是使用 MSINEWINSTANCE。
https://msdn.microsoft.com/en-us/library/aa370326(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/aa369528(v=vs.85).aspx
这样您就不会每次都更改基本 MSI 文件。
为什么还要设置包码?
它在每次构建期间自动生成。
看一下 Package 元素的文档:
http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html
"产品或合并模块的包代码 GUID。编译产品时,不应设置此属性以允许为每个构建生成包代码。编译合并模块时,此属性必须设置为模块化指南。 ”
我需要它,因为 MSI 在各自的包代码中创建了缓存,这限制了我们使用 MSI 创建另一个应用程序实例,所以我这样做了
using (var database = new Database(@"D:\\Nirvana\\WorkingCopy\\trunk\\proj1\\installer.msi", DatabaseOpenMode.Direct))
{
database.SummaryInfo.RevisionNumber = "{" + Guid.NewGuid() + "}";
}
我扩展了 Nikolay 脚本以自动生成随机 GUID。该脚本还支持拖放和通过参数调用(因此您可以通过 cscript 轻松地自动化它),它会在创建 Windows Installer 对象之前检查文件是否可写(如果文件被某些应用程序锁定,例如 InstEd,它将抛出错误)。
Set objArgs = Wscript.Arguments
Set objFso = CreateObject("scripting.filesystemobject")
'iterate through all the arguments passed
' https://community.spiceworks.com/scripts/show/1653-drag-drop-vbscript-framework
For i = 0 to objArgs.count
on error resume next
'try and treat the argument like a folder
Set folder = objFso.GetFolder(objArgs(i))
'if we get an error, we know it is a file
If err.number <> 0 then
'this is not a folder, treat as file
ProcessFile(objArgs(i))
Else
'No error? This is a folder, process accordingly
For Each file In folder.Files
ProcessFile(file)
Next
End if
On Error Goto 0
Next
Function ProcessFile(sFilePath)
' http://www.wisesoft.co.uk/scripts/vbscript_file_modified_date.aspx
' Set objFile = objFSO.GetFile(sFilePath)
' MsgBox "Now processing file: " & CDATE( objFile.DateLastModified)
If Not IsWriteAccessible(sFilePath) Then WScript.Echo "Error persisting summary property stream" : Wscript.Quit 2
'Do something with the file here...
' https://stackoverflow.com/questions/31536349/set-package-code-of-msi-using-vbscript
Set installer = CreateObject("WindowsInstaller.Installer")
Set summary = installer.SummaryInformation(sFilePath, 2)
summary.Property(9) = CreateGuid()
summary.Persist
End Function
' https://stackoverflow.com/questions/968756/how-to-generate-a-guid-in-vbscript
Function CreateGuid()
CreateGuid = Left(CreateObject("Scriptlet.TypeLib").Guid,38)
End Function
' https://stackoverflow.com/questions/12300678/how-can-i-determine-if-a-file-is-locked-using-vbs
Function IsWriteAccessible(sFilePath)
' Strategy: Attempt to open the specified file in 'append' mode.
' Does not appear to change the 'modified' date on the file.
' Works with binary files as well as text files.
' Only 'ForAppending' is needed here. Define these constants
' outside of this function if you need them elsewhere in
' your source file.
Const ForReading = 1, ForWriting = 2, ForAppending = 8
IsWriteAccessible = False
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Dim nErr : nErr = 0
Dim sDesc : sDesc = ""
Dim oFile : Set oFile = oFso.OpenTextFile(sFilePath, ForAppending)
If Err.Number = 0 Then
oFile.Close
If Err Then
nErr = Err.Number
sDesc = Err.Description
Else
IsWriteAccessible = True
End if
Else
Select Case Err.Number
Case 70
' Permission denied because:
' - file is open by another process
' - read-only bit is set on file, *or*
' - NTFS Access Control List settings (ACLs) on file
' prevents access
Case Else
' 52 - Bad file name or number
' 53 - File not found
' 76 - Path not found
nErr = Err.Number
sDesc = Err.Description
End Select
End If
' The following two statements are superfluous. The VB6 garbage
' collector will free 'oFile' and 'oFso' when this function completes
' and they go out of scope. See Eric Lippert's article for more:
' http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/when-are-you-required-to-set-objects-to-nothing.aspx
'Set oFile = Nothing
'Set oFso = Nothing
On Error GoTo 0
If nErr Then
Err.Raise nErr, , sDesc
End If
End Function