tags:

views:

1089

answers:

5
+2  Q: 

msi file reading

is there any way to read the properties inside the msi file.

for example given a msi file name Testpackage.msi

i need to find productName PackageCode version

this i am going to use it with WMI uninstall string objPath = string.Format("Win32_Product.IdentifyingNumber='{0}',Name='{1}',Version='{2}'", "{AC9C1263-2BA8-4863-BE18-01232375CE42}", "testproduct", "10.0.0.0");

update: using Orca is a great option, if this can be achieved programatically, then i can use this to generate automatic release notes. and in uninstall program too.

+5  A: 

You can use Microsoft's Orca.exe. Orca will allow you to open the MSI and edit/view all the tables in it. You will have to download the entire Windows SDK in order to get it, but thankfully that is free.

One alternative (which might be faster due to the download size of the SDK) is to use dark.exe from the WiX project. Dark is a MSI decompiler, which will export everything into an XML file and collection of resources. The XML it outputs will have the information you are looking for.

csexton
Orca itself is also available from here -> http://astebner.sts.winisp.net/Tools/Orca.zip
Steven Murawski
A: 

If you don't need to do it in code, you can use the Orca tool from Microsoft.

Kieron
+3  A: 

You can use the COM-based API for working with MSI, and do something like

Function GetVersion(ByVal msiName)

    Const msiOpenDatabaseModeReadOnly = 0
    Dim msi, db, view

    Set msi = CreateObject("WindowsInstaller.Installer")
    Set db = msi.OpenDataBase(msiName, msiOpenDatabaseModeReadOnly)
    Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'")
    Call view.Execute()

    GetVersion = view.Fetch().StringData(1)

End Function
Arnout
Also take a look at the MsiInfo.exe command line tool (also a part of the Windows SDK). It can read and write the summary information of an MSI (Including the Oh-so-painful Package Code)
Evan Larkin
+2  A: 

I wanted to comment Arnout's answer, but wasn't allowed to. I just want to mention that things have gotten even easier now. There is a full .NET wrapper for the Windows Installer object model, so you can avoid any COM interop clunkiness.

The wrapper is called "Deployment Tools Foundation" (DTF) and here is the basic description: "Deployment Tools Foundation is a rich set of .NET class libraries and related resources that together bring the Windows deployment platform technologies into the .NET world. It is designed to greatly simplify deployment-related development tasks while still exposing the complete functionality of the underlying technology".

DTF is included with new WIX releases.

Here is a stripped-down sample:

using (var db = new Database(FullPath, DatabaseOpenMode.ReadOnly))
{    
  PackageCode = db.SummaryInfo.RevisionNumber;
  AppVendor = db.SummaryInfo.Author;
  AppName = db.SummaryInfo.Title;
  ProductName = db.SummaryInfo.Subject;
  ProductCode = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                 "`Property` WHERE `Property` = 'ProductCode'");
  AppVersion = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                 "`Property` WHERE `Property` = 'ProductVersion'");
  UpgradeCode = (string)db.ExecuteScalar("SELECT `Value` FROM "+
                 " `Property` WHERE `Property` = 'UpgradeCode'");
}
Glytzhkof
The DTF is hidden in WixInstallPath\SDK directory, Microsoft.Deployment.*.dlls.
deerchao
+1  A: 

Here's a similar example in VBScript which I use as part of my build process in creating bootstrapper executables...

Option Explicit
Const MY_MSI = "product.msi"

Dim installer, database, view, result, sumInfo, sPackageCode

Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase (MY_MSI, 0)

Set sumInfo = installer.SummaryInformation(MY_MSI, 0)
sPackageCode =  sumInfo.Property(9) ' PID_REVNUMBER = 9, contains the package code.

WScript.Echo "ProductVersion=" & getproperty("ProductVersion")
WScript.Echo "ProductCode=" & getproperty("ProductCode") 
WScript.Echo "PackageCode=" & sPackageCode 
WScript.Echo "ProductName=" & getproperty("ProductName") 

Function getproperty(property)

    Set view = database.OpenView ("SELECT Value FROM Property WHERE Property='" & property & "'")
    view.Execute
    Set result = view.Fetch
    getproperty = result.StringData(1)

End Function
sascha

related questions