Как найти номер версии продукта MSI с помощью PowerShell? - PullRequest
11 голосов
/ 05 января 2012

В нашей конечной поставке есть много файлов MSI .

Я бы позаботился о том, чтобы у них было правильное название продукта и версия продукта. и делать это вручную.

Как это сделать с помощью PowerShell?

Ответы [ 2 ]

25 голосов
/ 05 января 2012

Это должен был быть простой ответ ... Для запуска установщика Windows есть COM-объект , который вы можете использовать:

ProgID: WindowsInstaller.Installer

Однако при создании объекта с помощью PowerShell вы не получаете никаких свойств или методов:

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

... Ничего: - (

Видимоэто проблема с PowerShell и его системой адаптации типов. См. этот пост в блоге для временного решения.

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

Если вы используете VBScript, у вас не должно быть этой проблемы.

РЕДАКТИРОВАТЬ:

Вот некоторый VBScript, который получит версию I найдена :

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

Вы можете вызвать это из PowerShell:

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

Обновление! Эта проблема с адаптацией типов меня расстраивала, и я не был доволен решением VBS. После небольшого исследования я нашел способ сделать это в PowerShellправильно. Я адаптировал код из его записи в блоге . Наслаждайтесь!

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"
2 голосов
/ 04 июля 2014

(Извините, нет представителя, чтобы добавить комментарий к принятому ответу)

Ответ от @davidmartin был очень полезным для меня.

Единственный бит, который мне нужно было добавить, - это закрыть объект перед возвратом версии, в противном случае дескриптор остается открытым в msi, и в дальнейшем доступ может завершиться ошибкой:

$View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null)

return $productVersion
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...