Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest solution to replace a tiny file inside an MSI?

Many of our customers have access to InstallShield, WISE or AdminStudio. These aren't a problem. I'm hoping there is some way I can provide our smaller customers without access to commercial repackaging tools a freely available set of tools and steps to do the file replacement themselves.

Only need to replace a single configuration file inside a compressed MSI, the target user can be assumed to already have Orca installed, know how to use this to customize the Property table (to embed license details for GPO deployment) and have generated an MST file.



Disclaimer: this is very similar to another question but both questions and answers in that thread are not clear.

like image 706
saschabeaumont Avatar asked Nov 26 '08 06:11

saschabeaumont


People also ask

How do I modify an msi file?

Similar to Orca, to edit your MSI package, right-click it and select “Open with Advanced Installer”. Once the MSI database has loaded in Advanced Installer, you will notice a left menu pane where you will find all the options you need to directly edit your MSI.

How do I find out what's inside an msi file?

View MSI files by launching the app, or by right-clicking an MSI file in File Explorer and choosing "Open in MSI Viewer".


2 Answers

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.

like image 105
saschabeaumont Avatar answered Oct 20 '22 20:10

saschabeaumont


IMHO this kind of scenario indicates a missing feature in the application being installed, and is easier to fix in the application than hacking around with the MSI.


Admin Image

Let me first say that a simple way to "solve" this for your users, is to tell them to run an Admin Installation of your MSI. This will essentially extract all the files from the internal CABs and put all files in the specified folder:

msiexec.exe /a myinstaller.msi TARGETDIR=C:\AdminImage

Your users can then go directly into the extracted folder structure and update the file in question and then map the directory to other PC's and install the MSI. There could be side effects to this relating to the file having a hash value in the MSI (to avoid spoofing), but in most cases it works fine.


Run XML XPath Query

New versions of deployment tools such as Installshield and Wix feature built-in support for running XPath queries during the installation and hence write sections dynamically.


Application Update

Setting up an application on a PC involves several steps. First there is the deployment of content to the machine - this should be done using an MSI, no question about it. However, in most advanced applications several "post installation configuration tasks" similar to this "config file update" are required.

It is almost always better to defer these configuration tasks until the application launch, rather than to implement features in the MSI. There are many reasons for this, but the most important being that only the application EXE will be guaranteed to run in the correct user context. MSI files can be run with system rights, a different user account or via some other mechanism.

What we generally recommend is to use the MSI to get all required content onto the PC. Then tag the registry to indicate to the application that it's the first launch (for updates, you can increment a counter or write the new version number to HKLM). Then the application can perform the final configuration steps in its startup routine. It can copy a default config.xml file from somewhere in %ProgramFiles% and copy it to the user profile. Then it can read required values from HKLM written by the MSI, and then update the config.xml file with these values.

In general: avoid configuration steps performed by MSI or any other setup mechanism. Concentrate on writing the required files and registry items to the machine, and then let the application itself set up a proper runtime environment. This will allow much better deployment control. It is better "Encapsulation" if you like. The MSI sends a "message" to the application via the registry, and the application knows "how to set itself up correctly" based on the messages.

like image 44
Stein Åsmul Avatar answered Oct 20 '22 21:10

Stein Åsmul