How can I programmatically read the properties inside an MSI file?
Asked Answered
I

5

7

Is there a way to read the properties inside an MSI file?

For example, given a MSI file named 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");

Using Orca is a great option, if this can be achieved programmatically. Then I can use this to generate automatic release notes. And in un-installing program too.

Inconclusive answered 18/11, 2008 at 14:14 Comment(0)
C
8

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
Contiguous answered 30/11, 2008 at 10:32 Comment(2)
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)Bivins
Please see my answer below for what I believe is a simpler and more reliable way to access an MSI.Regenerator
A
7

WiX toolset: WiX quick-start tips (collection of links to resources). WiX installs DTF.


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.

DTF - Getting Started: Main file: Microsoft.Deployment.WindowsInstaller.dll

  1. Download and install the WiX toolkit
  2. Find the files below in the WixInstallPath\SDK directory

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".

Here is a stripped-down, hands-on 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'");
}

Primary DTF files (the latter two are the most used ones):

  • Microsoft.Deployment.Compression.dll - Framework for archive packing and unpacking.
  • Microsoft.Deployment.Compression.Cab.dll - Implements cabinet archive packing and unpacking.
  • Microsoft.Deployment.Resources.dll - Classes for reading and writing resource data in executable files.
  • Microsoft.Deployment.WindowsInstaller.dll - Complete .NET based class library for the Windows Installer APIs.
  • Microsoft.Deployment.WindowsInstaller.Package.dll - Extended classes for working with Windows Installer installation and patch packages.

Just create a C# project, reference these files, and code your own deployment application with whatever control you desire and need. I am not set up with the tools for DTF at the moment, but see this sample for a general idea of how a C# program would work.

  • DTF is included with WIX. Download WiX from here.
  • The DTF dlls are in the SDK folder in the main WiX installation folder (the default location is: %ProgramFiles(x86)%\WiX Toolset v3.10\SDK). The version number will probably be different by the time you see this. Just look for the WiX folder under %ProgramFiles(x86)%.
  • Look for the DTF help files in the "doc" folder. DTF.chm and DTFAPI.chm. Absolutely excellent documentation for the object model and its usage.
  • See this serverfault.com post for some more DTF details
  • Some starter suggestions for working with WiX
Amund answered 30/6, 2009 at 3:40 Comment(1)
The DTF is hidden in WixInstallPath\SDK directory, Microsoft.Deployment.*.dlls.Retaretable
J
6

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.

Jacalynjacamar answered 18/11, 2008 at 14:23 Comment(2)
Orca itself is also available from here -> astebner.sts.winisp.net/Tools/Orca.zipInnermost
Link seems not anymore validThermoplastic
S
3

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 
Succuss answered 30/6, 2009 at 13:0 Comment(0)
C
0

I found a lightweight non-programmatic solution in lessmsi. It apparently uses wix and just explodes the whole .msi into a specified folder. (It also has a UI but it didn't render great for me on Win7).

Calcimine answered 2/2, 2011 at 22:33 Comment(1)
What didn't render great? Please let me know on the google code site and I'll investigate. Or, since it is fully open source feel free to submit a patch ;)Milkwhite

© 2022 - 2024 — McMap. All rights reserved.