1

I am changing product code, upgrade code and product name of MSI by editing MSI database.

With reference :- http://www.codeproject.com/Articles/383481/Editing-an-MSI-Database

I am able to change all parameters above but unable to change Package Code.

Suggest a way to change package code.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Keshav
  • 1,917
  • 18
  • 22

5 Answers5

3

Found a way to do it with vbscript, just out of curiosity: The "property #9" is the package code (revision number).

Set wi = CreateObject("WindowsInstaller.Installer")
Set summary = wi.SummaryInformation("your.msi", 2)
summary.Property(9) = "{PUT-NEW-GUID-HERE}"
summary.Persist
Nikolay
  • 10,752
  • 2
  • 23
  • 51
1

I'm guessing that the requirement here is to install the same MSI multiple times, which means they need to change that set of guids. However the more normal way to solve that problem is with 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

so that you are not changing the base MSI file every time.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • I agree with you but our requirement is to create independent instances...I already looked into MSINEWINSTANCE but there is not a problem I think in changing base MSI ? – Keshav Jul 22 '15 at 05:20
0

Why do you even have the need to set the package code?

Its auto generated during each build.

Take a look at the documentation of the Package element:

http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html

"The package code GUID for a product or merge module. When compiling a product, this attribute should not be set in order to allow the package code to be generated for each build. When compiling a merge module, this attribute must be set to the modularization guid."

Kiran Hegde
  • 680
  • 4
  • 14
0

I needed it because MSI created cache in respective package code which restricts us to make another instance of application using MSI so I did this by

using (var database = new Database(@"D:\\Nirvana\\WorkingCopy\\trunk\\proj1\\installer.msi", DatabaseOpenMode.Direct))
{
     database.SummaryInfo.RevisionNumber = "{" +  Guid.NewGuid() + "}";
}   
Nikolay
  • 10,752
  • 2
  • 23
  • 51
Keshav
  • 1,917
  • 18
  • 22
  • I don't quite understand your problem either. Normally, nobody generates PackageCodes, they are auto-generated on build. Why do you want to change a value one more time after build (to another random guid)?! – Nikolay Jul 21 '15 at 13:45
  • Because I want to create multiple instances from same MSI package rather than building MSI again . So it is necessary to change Package codes in order for you to create independent instances from same MSI. – Keshav Jul 22 '15 at 05:22
0

I extended the Nikolay script for generating a random GUID automatically. The script also support drag and drop and be called through arguments (so you can easily automate it through cscript) and it checks if the file is writable before creating Windows Installer object (if the file is locked by some application, like InstEd, it will throw an error).

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
eduardomozart
  • 1,444
  • 15
  • 14