I'd like to read an MSI file into a MemoryStream (or something similar), and modify it. What's the easiest way to do this, without corrupting the MSI?
All I need to be able to do is modify the value of one of the properties in the MSI. I'd prefer something in .Net, but I'm open to other platforms.
Update:
Here's my working code, using the Windows platform SDK, a COM reference to Microsoft Windows Installer Object Library and namespace WindowsInstaller:
Installer installer = Activator.CreateInstance(Type.GetTypeFromProgID("WindowsInstaller.Installer")) as Installer;
Database msi = installer.OpenDatabase("WixTest.msi", MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
View view = msi.OpenView("update `Property` SET `Property`.`Value`='99' where `Property`='USERID'");
view.Execute(null);
msi.Commit();
Check out the Windows SDK, there are a bunch of samples included on using the Windows Installer API.
Here's a simplified version of a command line VBScript I use to do this:
Option Explicit
Const msiOpenDatabaseModeReadOnly = 0
Const msiOpenDatabaseModeTransact = 1
Dim openMode : openMode = msiOpenDatabaseModeTransact
Dim argCount:argCount = Wscript.Arguments.Count
If (argCount < 3) Then WScript.Echo "usage: msisetproperty.vbs <msi> <property> <value>" : WScript.Quit 1
Dim MY_MSI : MY_MSI = Wscript.Arguments(0)
Dim sProp1 : sProp1 = Wscript.Arguments(1)
Dim sVal1 : sVal1 = Wscript.Arguments(2)
Dim filesys : Set filesys=CreateObject("Scripting.FileSystemObject")
If Not filesys.FileExists(MY_MSI) Then WScript.Echo "Unable to find msi, exiting" : WScript.Quit 1
Dim installer, database, view, result
Set installer = CreateObject("WindowsInstaller.Installer")
Dim sumInfo : Set sumInfo = installer.SummaryInformation(MY_MSI, 0)
Set database = installer.OpenDatabase (MY_MSI, openMode)
Set view = database.OpenView ("UPDATE Property SET Value='" & sVal1 & "' WHERE Property='" & sProp1 & "'")
view.Execute
database.Commit
Set database = nothing
Even though this post is really old, for the sake of users who happen to get here via search engines, there is a very neat .Net library which implements nearly all of the functionality of the Windows Installer SDK and is actively maintained by Rob Mensching, a senior developer at Microsoft. Its present in the Wix Toolset and you can get v3.6 RC0 here.
After installing this toolset, add a reference to Microsoft.Deployment.WindowsInstaller.dll present in the install directory of this toolset and you are good to go.
You can easily load the whole msi database into a DataSet and perform the required read/write operations and finally commit the changes to the msi.