
I recently had the need to adapt a feisty MSI installer that was not succumbing to the normal PROPERTY command line or transform file methods. Whether this was due to a fault while packaging, a deliberate choice during packaging, or a mind-obliteratingly rare instance of me making a mistake, I don’t know.
The problem: MSI installer giving entirely too much sass.
The solution: Delete a record from a table within the installer.
The means: (Keep reading to find out! Ohhhh boy!)
Below is a PowerShell script that will remove a record from an MSI installer table. The point, The want, nay — The Impetus — is that the com object used is native to Windows and does not require installing Orca. This means that you (I/myself/the-one-who-is-not “you”) can script the intake of the problematic installer and deployment without the extra Orca (a vicious sea mammal that kills for fun) ordeal.
Param (
[Parameter(Mandatory=$true)]$MsiPath,
[Parameter(Mandatory=$true)]$TableName,
[Parameter(Mandatory=$true)]$PropertyName,
$PropertyValue=""
)
# Create a new Windows Installer Object
$windowsInstaller = New-Object -ComObject WindowsInstaller.Installer
# Open the MSI database in transaction mode
try {
$database = $windowsInstaller.OpenDatabase($msiPath, 1)
} catch {
Write-Host "Error opening database: $_"
exit
}
# Query to access the specific row in the table
# Literal backticks are required for table and column names with spaces
$query = "SELECT * FROM ``$TableName`` WHERE ``$PropertyName`` = '$PropertyValue'"
# Open a view of the table
try {
$view = $database.OpenView($query)
$view.Execute()
} catch {
Write-Host "Error opening view: $_"
$database.Commit()
$database = $null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null
exit
}
# Delete record
try {
$record = $view.Fetch()
if ($record -ne $null) { $view.Modify(6, $record) }
} catch {
Write-Host "Error modifying view: $_"
}
$view.Close()
$database.Commit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($database) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstaller) | Out-Null
