tags:

views:

2920

answers:

4

I want to replace a single file inside a msi. How to do it?

+4  A: 

You need to extract the CAB file stream from your msi using MsiDB.exe (supplied with the Windows Installer SDK). Run it from the command line with the -x option and specify the name of the cab file - this is listed in the Media table in the msi database.

Alternatively you can skip this part if you specify the "Package Files as:" option in the VSI options to "Compresses in Cabinet Files" to have the cab file left out of the msi when it's built (it will be created in the same directory as the msi).

Once extracted you can change the specified file in the cab folder - its name has been mangled so you need to find out what msi name for the file is in the file table and then rename your new file to that.

Once done you can pop it back in with the MsiDB utility using the -a option.

Before you add with -a you need to use msidb -k to remove the cab from the MSI.

splattne
VSI = Visual Studio Installer. http://www.devx.com/vb2themax/Article/19893
splattne
A: 

The easiest way to do it is to repackage MSI:

  1. Open MSI file in Wise for Windows Installer. Choose an option to to extract files.
  2. Locate the file on disk and replace it.
  3. Build MSI.

These steps should also work for InstallShield.

Pavel Chuchuva
A valid solution for someone who has access to commercial repackaging tools I guess... but if that was the case I doubt the question would be asked ;)
sascha
A: 

Very simple example code to replace a file inside an MSI. This does not stream the new file/CAB back into the MSI but requires the CAB to be in the same directory as the MSI for installation to succeed. I'm sure with a little more effort you could alter the code to stream the CAB back in.

Const MSI_SOURCE = "application.msi"
Const FILE_REPLACE = "config.xml"

Dim filesys, installer, database, view
Dim objFile, size, result, objCab

Set filesys=CreateObject("Scripting.FileSystemObject")
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (MSI_SOURCE, 1)

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

objCab.CreateCab "config.cab", False, False, False
objCab.AddFile FILE_REPLACE, filesys.GetFileName(FILE_REPLACE)
objCab.CloseCab

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 & "', 'config.cab')")
view.Execute

Set view = database.OpenView ("UPDATE File SET FileSize = " & size & ", Sequence = " & seq & " WHERE File = '" & LCase(FILE_REPLACE) & "'")
view.Execute
sascha
A: 

What is the type of objCab ?????

MSM