If you have experience working with MSI Windows Installer, you’re probably aware that the Windows Installer database consists of multiple interconnected tables, following a standard format for managing components.

The standardized format of MSI Windows Installer makes it an excellent choice for automating various tasks.

Let’s say you need to search for MSI packages within your infrastructure that install a specific version of a file. PowerShell can come to the rescue. In this article, we will walk you through the process of creating a PowerShell script that allows you to access a particular MSI table.

Why PowerShell?

First and foremost, PowerShell comes pre-installed on all Windows systems, including both clients and servers. It offers a wide range of modules that can be leveraged for various tasks, as per your requirements.

PowerShell also provides a user-friendly Integrated Scripting Environment (ISE) that enables you to write, test, and debug your scripts in a GUI editor mode. It enhances the scripting experience with helpful features like syntax coloring, tab completion, context-sensitive help, and more.

Full Powershell script

Note: The script takes the $SearchFolder, $SearchForFileName and $SearchForFileVersion as inputs – you can modify these 3 variables as per your needs.

$SearchFolder = "C:\Downloads\MSI"
$SearchForFileName = "libflac_plugin.dll"
$SearchForFileVersion = ""
$MSIFilePathArray = Get-ChildItem -Path $SearchFolder -File -Recurse | Where-Object { $_.Name -Match '.*\.msi$' } | % { $_.FullName }
ForEach ($MSIFilePath in $MSIFilePathArray)
    [bool] $SearchFor = $false
    # Creating WI object and load MSI database
    $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
    $WindowsInstallerDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @(($MSIFilePath), 0))
    # Open the Property-view
    $WindowsInstallerDatabaseView = $WindowsInstallerDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $WindowsInstallerDatabase, "SELECT * FROM File")
    $WindowsInstallerDatabaseView.GetType().InvokeMember("Execute", "InvokeMethod", $null, $WindowsInstallerDatabaseView, $null)
    # Loop through the table
    $WindowsInstallerDatabaseRow = $WindowsInstallerDatabaseView.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $WindowsInstallerDatabaseView, $null)
    while (($null -ne $WindowsInstallerDatabaseRow) -AND (-Not $SearchFor)) {
        # Add property and value to hash table
        If (($WindowsInstallerDatabaseView.GetType().InvokeMember("StringData", "GetProperty", $null, $WindowsInstallerDatabaseRow, 3) -like "*$SearchForFileName") -AND ($WindowsInstallerDatabaseView.GetType().InvokeMember("StringData", "GetProperty", $null, $WindowsInstallerDatabaseRow, 5) -eq $SearchForFileVersion))
            $SearchFor = $true
        # Fetch the next rowtch", "InvokeMethod", $null, $WindowsInstallerDatabaseView, $null)
        $WindowsInstallerDatabaseRow = $WindowsInstallerDatabaseView.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $WindowsInstallerDatabaseView, $null)
    $WindowsInstallerDatabaseView.GetType().InvokeMember("Close", "InvokeMethod", $null, $WindowsInstallerDatabaseView, $null)
    If ($SearchFor)
        Write-Host "File" $SearchForFileName "version" $SearchForFileVersion "found in" $MSIFilePath


Bogdan Mitrache