Bl4cKh4wK ZG
Bl4cKh4wK ZG

Reputation: 27

Powershell Get MSI Information

I'm trying to extract some information from a MSI file like ProductCode or CustomAction. I've used other scripts from the internet and edited them, but my script has some issues.

This is only a little piece of the original code, but if I execute this, I get this error message:

WARNING: Exception calling "InvokeMember" with "5" argument(s): "OpenView,Sql"

function Get-MSIFileInformationList {
[CmdletBinding()]
[OutputType([string])]
param(
[parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]$Path,

[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$FROM = "Property",

[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$LIKE = "Property",

[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$WHERE = "Property",

[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$SELECT = "Property"
)

Begin
{
}
Process {
    try {
        # Read property from MSI database
        $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
        $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($Path.FullName, 0))
        $Query = "SELECT $SELECT FROM $FROM WHERE $WHERE LIKE '%$($LIKE)%'"
        # $Query = "SELECT Value FROM CustomAction WHERE Action = '$($CustomAction)'"
        Write-Host 1
        $View = $MSIDatabase.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $MSIDatabase, ($Query))
        Write-Host 2
        $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null) | Out-Null
        Write-Host 3
        $Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)
        try {
        Write-Host 4
            $Value = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
            Write-Host 5

            # Commit database and close view
            $MSIDatabase.GetType().InvokeMember("Commit", "InvokeMethod", $null, $MSIDatabase, $null) | Out-Null
            Write-Host 6
            $View.GetType().InvokeMember("Close", "InvokeMethod", $null, $View, $null) | Out-Null
            Write-Host 7
            $MSIDatabase = $null
            $View = $null
        } catch {
            $Value = "-"
        }
        # Return the value

        return $Value

    } 
    catch {
        Write-Warning -Message $_.Exception.Message ; break
        return ""
    }
}
End {
    # Run garbage collection and release ComObject       [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) | Out-Null
    [System.GC]::Collect()
}
}

Upvotes: 1

Views: 1701

Answers (1)

Frode F.
Frode F.

Reputation: 54971

MSI-databases doesn't support LIKE as it only implements a subset of the SQL-Language (https://msdn.microsoft.com/en-us/library/windows/desktop/aa372021.aspx). This should work:

$Query = "SELECT $SELECT FROM $FROM WHERE $WHERE = 'ProductName'"

If you need to filter, you would have to do it on the results of SELECT * FROM Property.

Upvotes: 2

Related Questions