How do I find the MSI product version number using PowerShell?

前端 未结 3 1834
长情又很酷
长情又很酷 2020-12-28 09:08

Our end deliverable has lot of MSI files.

I would ensure whether they has correct product name and product version.

I am using Orca and doing it manually.

3条回答
  •  一向
    一向 (楼主)
    2020-12-28 09:50

    This should have been an easy answer... To start with Windows Installer has a COM object you can use:

    ProgID: WindowsInstaller.Installer

    However when you create an object out of with PowerShell you don't get any of the properties or methods:

    $object = New-Object -Com WindowsInstaller.Installer
    $object | gm
    

    ...Nothing :-(

    Apparently this is a problem with PowerShell and its type adapting system. See this blog post for a work around.

    http://www.snowland.se/2010/02/21/read-msi-information-with-powershell/

    If you use VBScript you shouldn't have this problem.

    EDIT:

    Here's some VBScript that will get the version I found:

    Const msiOpenDatabaseModeReadOnly = 0
    Dim msi, db, view
    
    Set msi = CreateObject("WindowsInstaller.Installer")
    Set db = msi.OpenDataBase("C:\Users\andy\Desktop\Module.msi", msiOpenDatabaseModeReadOnly)
    Set view = db.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'")
    Call view.Execute()
    
    GetVersion = view.Fetch().StringData(1)
    Wscript.Echo GetVersion
    

    You can call this from PowerShell:

    $version = & cscript.exe /nologo GetVersion.vbs
    

    Update! This type adaption problem was frustrating me and I wasn't happy with the VBS solution. After a bit of research I found a way to do this in PowerShell proper. I adapted code from his blog entry. Enjoy!

    function Get-MsiDatabaseVersion {
        param (
            [string] $fn
        )
    
        try {
            $FullPath = (Resolve-Path $fn).Path
            $windowsInstaller = New-Object -com WindowsInstaller.Installer
    
            $database = $windowsInstaller.GetType().InvokeMember(
                    "OpenDatabase", "InvokeMethod", $Null, 
                    $windowsInstaller, @($FullPath, 0)
                )
    
            $q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
            $View = $database.GetType().InvokeMember(
                    "OpenView", "InvokeMethod", $Null, $database, ($q)
                )
    
            $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null)
    
            $record = $View.GetType().InvokeMember(
                    "Fetch", "InvokeMethod", $Null, $View, $Null
                )
    
            $productVersion = $record.GetType().InvokeMember(
                    "StringData", "GetProperty", $Null, $record, 1
                )
    
            $View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null)
    
            return $productVersion
    
        } catch {
            throw "Failed to get MSI file version the error was: {0}." -f $_
        }
    }
    
    Get-MsiDatabaseVersion "Installer.msi"
    

提交回复
热议问题