首页 > 解决方案 > PowerShell 将 .EXE 版本与 .MSI 版本进行比较

问题描述

早上好,我正在编写一个脚本,它将已安装的 .exe 版本与另一个位置的 .msi 版本进行比较。如果版本不匹配,它将安装较新的 .msi。我必须编写代码才能获得版本号,但它一直说它们不匹配;他们有,但也没有。

.EXE Version is 9.1.3.3108
.MSI Version is 9.1.3

下面是我的代码

Function Get-MsiDBVersion {
    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 $_
    }
}

$RACToolsVersion = Get-MsiDBVersion "C:\Source\BuildSource\Laptop\02-AdminCenter\RACTools\RACTools_x64.msi"

if((get-item "C:\Program Files\Dell\SysMgt\rac5\racadm.exe").VersionInfo.FileVersion -match $RACToolsVersion){
>>     write-host "yes match"
>> }else{
>>     write-host "no match"}

当我运行它时,我总是得到no match

标签: powershellwindows-installerexecomparison-operators

解决方案


我以前遇到过这个问题 - 请参阅此处:https ://www.alkanesolutions.co.uk/2016/12/13/query-windows-installer-msi-using-powershell/

特别是底部的注释!

“在编写 Powershell 函数以返回单个值(例如字符串)时,请确保将任何对 'Execute' 或 'Close' 的调用通过管道传递给 'Out-Null'(请参见上文)。这将阻止函数返回System.Object[](因为 Powershell 函数返回函数的全部输出,而不仅仅是 'return' 语句之后的值)!”

因此,在您的情况下,您的函数返回前导空格,可以像这样修复(注意 out-null):

Function Get-MsiDBVersion {
    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) | Out-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) | Out-Null


        return $productVersion

    } catch {
        throw "Failed to get MSI file version the error was: {0}." -f $_
    }
}

推荐阅读