Simplest solution to replace a tiny file inside an MSI?

Okay, revisiting this question with my own answer providing nice little VB script that will do all heavy lifting. As mentioned in the original question, the aim was provide a simple solution for sysadmin users to make the updates/changes themselves.

Below is a simplified version of the code I’m currently providing to customers

Option Explicit

Const MY_CONFIG = "MyConfigApp.xml"
Const CAB_FILE = "config.cab"
Const MSI = "MyApp.msi"

Dim filesys : Set filesys=CreateObject("Scripting.FileSystemObject")

If filesys.FileExists("temp.tmp") Then filesys.DeleteFile("temp.tmp")
filesys.CopyFile MSI, "temp.tmp"

Dim installer, database, database2, view
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("temp.tmp", 1)
Set database2 = installer.OpenDatabase (MSI, 1)

If Not filesys.FileExists(MY_CONFIG) Then WScript.Quit 2 ' No config file, abort!

Dim objFile, size, result, seq, objCab

' MakeCab object has been depreciated so we fallback to makecab.exe for with Windows 7
On Error Resume Next ' Disable error handling, for a moment
Set objCab = CreateObject("MakeCab.MakeCab.1") 
On Error Goto 0  ' Turn error handling back on

If IsObject(objCab) Then ' Object creation successful - use XP method   
    objCab.CreateCab CAB_FILE, False, False, False
    objCab.AddFile MY_CONFIG, filesys.GetFileName(MY_CONFIG)
    objCab.CloseCab
    Set objCab = Nothing
Else ' object creation failed - try Windows 7 method
    Dim WshShell, oExec
    Set WshShell = CreateObject("WScript.Shell")
    Set oExec = WshShell.Exec("makecab " & filesys.GetFileName(MY_CONFIG) & " " & CAB_FILE)
End If

Set objFile = filesys.GetFile(MY_CONFIG)
size = objFile.Size

Set view = database.OpenView ("SELECT LastSequence FROM Media WHERE DiskId = 1")
view.Execute
Set result = view.Fetch
seq = result.StringData(1) + 1 ' Sequence for new configuration file

Set view = database.OpenView ("INSERT INTO Media (DiskId, LastSequence, Cabinet) VALUES ('2', '" & seq & "', '" & CAB_FILE & "')")
view.Execute

Set view = database.OpenView ("UPDATE File SET FileSize = " & size & ", Sequence = " & seq & ", FileName="MYC~2.CNF|MyConfigApp.xml" WHERE File="" & MY_CONFIG & """)
view.Execute

database.GenerateTransform database2, "CustomConfig.mst"
database.CreateTransformSummaryInfo database2, "CustomConfig.mst", 0, 0
filesys.DeleteFile("temp.tmp")

Set view = nothing
Set installer = nothing
Set database = nothing
Set database2 = nothing
Set filesys = Nothing
WScript.Quit 0

Update: The MakeCab.MakeCab.1 object has been depreciated, code updated to now work with Windows 7.

Leave a Comment