This is an example of how we can use PowerShell to read MSI windows installer properties.
It’s a reusable function where we can pass in any MSI property name (ProductCode, ProductName, ProductVersion, ALLUSERS etc) and return the value as a string.
function Get-MSIProperty {
Param(
[String]$msipath,
[string]$msiproperty
)
try {
$propertyvalue = ""
$installer = New-Object -ComObject WindowsInstaller.Installer
$database = $installer.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $installer, @($msipath, 0))
$view = $database.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $database, ("SELECT Value FROM Property WHERE Property = '$msiproperty'"))
$View.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null) | Out-Null
$record = $View.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
if ($record) {
$propertyvalue = $record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1)
$view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null) | Out-Null
}
return $propertyvalue
}
catch {
throw 'Failed to get MSI property: {0}.' -f $_
} finally {
if ($record) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($record) | Out-Null }
if ($view) { [System.Runtime.InteropServices.Marshal]::ReleaseComObject($view) | Out-Null }
if ($database){ [System.Runtime.InteropServices.Marshal]::ReleaseComObject($database) | Out-Null }
if ($installer){[System.Runtime.InteropServices.Marshal]::ReleaseComObject($installer) | Out-Null }
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
}
}
$msifile = "C:\Alkane\alkane.msi"
$property = Get-MSIProperty $msifile "ProductCode"
write-host $property

