Updated 2007-11-02 15:46:09 by APN

According to Microsoft [1],

Microsoft® Windows® Installer is an installation and configuration service that reduces the total cost of ownership.

The second part of that statement might be open to debate but the infrastructure does provide flexibility and some sophisticated capabilities for shared installs, JIT installation, remote upgrades etc.

The Windows installer can be accessed through COM automation. Below is an example using TWAPI that enumerates installed products and versions. The same can also be done using WMI as illustrated in TWAPI and WMI.
  # List product versions that are installed through Windows Installer
  # Note this is a sample script for illustrative purposes. There is no
  # error handling as such.

  # MSI related stuff requires at least V2.0
  package require twapi 2.0

  # Array to map product state codes to display strings
  array set product_state_map {
      -7  "Not used"
      -6  "Misconfigured"
      -5  "Incomplete"
      -4  "Source absent"
      -1  "Unknown"
      0   "Broken"
      1   "Advertised"
      2   "Absent"
      3   "Local"
      4   "Source"
      5   "Installed"

  # Create a new Installer object
  set msiobj [twapi::comobj WindowsInstaller.Installer]

  # The Installer objects do not come with their own type library containing
  # method definitions so we need to manually load the definitions
  # for every object we create
  twapi::load_msi_prototypes $msiobj Installer

  # Get the product id list (type is StringList)
  set prodidsobj [$msiobj -get Products]
  set prodids    [list ]

  if {![$prodidsobj -isnull]} {
      twapi::load_msi_prototypes $prodidsobj StringList
      set count [$prodidsobj -get Count]
      for {set i 0} {$i < $count} {incr i} {
          lappend prodids [$prodidsobj -get Item $i]
  $prodidsobj -destroy

  # Now we have a list of product id's. Print the product name, version
  foreach prodid $prodids {
      set encoded_version [$msiobj -get ProductInfo $prodid Version]
      set version [expr {0xff & ($encoded_version >> 24)}].[expr {0xff & ($encoded_version >> 16)}].[expr {0xffff & $encoded_version}]
      set state [$msiobj -get ProductState $prodid]
      if {[info exists product_state_map($state)]} {
          set state $product_state_map($state)
      puts "[$msiobj -get ProductInfo $prodid ProductName] (V$version): $state"

  # Get rid of objects we created
  $msiobj -destroy

Category Windows