# 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 -destroyCategory Windows

