Search code examples
vbscriptwindows-installersetup-projectorca

How to change the contents of a file included in an *.msi with VBScript


Given an installer generated with a VS2010 Setup Project, I would like to swap out a .NET DLL with another one without changing the name.

I am already altering the msi file according to this question, swapping out the contents of an entry in the "Binary" table.

I have located the file in question using Orca. It resides in the only cabinet file. I have located this cabinet file in the "Media" table. I'm not sure how to change this cabinet file (API) and I suspect I'd have to change some information in the MSI database too (the "ProcessorArchitecture" record for the assembly in the "MsiAssemblyName" table).

Rationale: I'm making an installer for a Autodesk Revit 2011 plugin. These are registered using an assembly RevitAddinUtility.dll which must be bundled with the installer. This assembly comes in two flavors, one for 32-bit and one for 64-bit installations. I need to swap in the correct version when creating the installer, to avoid writing more than one installers.


Solution

  • Here is a workaround I'm using in the meantime:

    • add both files, one named RevitAddinUtility.dll the other RevitAddinUtility64.dll
    • in the PostBuild-Event, ask the user if the setup project should be for 64bit.
    • if yes, then change the names of the files:

      If 6 = MsgBox("Build for 64bit?", 4, "Setup PostBuild event for DesignPerformanceViewer") Then
          Dim installer : Set installer = Wscript.CreateObject("WindowsInstaller.Installer")
          Dim database : Set database = installer.OpenDatabase(PATH_TO_MSI, msiOpenDatabaseModeTransact)
          Dim sqlQuery : sqlQuery = "SELECT `FileName`, `Component_` FROM File"
          Dim view : Set view = database.OpenView(sqlQuery)
          view.Execute
          Dim record : Set record = view.Fetch
          While Not record Is Nothing        
              If InStr(record.StringData(1), "RevitAddInUtility.dll") Then  
                  record.StringData(1) = "REVITA~2.DLL|RevitAddInUtility32.dll"
                  view.Modify msiViewModifyUpdate, record    
              ElseIf InStr(record.StringData(1), "RevitAddInUtility64.dll") Then    
                  record.StringData(1) = "REVITA~1.DLL|RevitAddInUtility.dll"
                  view.Modify msiViewModifyUpdate, record    
              End If    
              Set record = view.Fetch
          Wend
          database.Commit   
      End If