如何使用Powershell从安装程序文件中获取DisplayName等属性信息
提取EXE安装包内置属性及版本比对实现方案
提取安装包元数据
针对常见的基于MSI封装的EXE安装包(如你举例的Notepad++安装包属于这类),可以通过以下两种PowerShell方式提取内置的DisplayName、版本等属性:
方法1:直接读取文件版本属性
大部分正规打包的安装包会把产品信息写入文件元数据,该方法执行最快:
# 替换为你的安装包实际路径 $installerPath = "C:\下载路径\npp.8.1.7.Installer.x64.exe" # 提取安装包文件内置元数据 $pkgInfo = Get-Item $installerPath | Select-Object -ExpandProperty VersionInfo # 输出所需属性 $pkgInfo.ProductName # 对应产品显示名称 $pkgInfo.ProductVersion # 对应安装包版本号
方法2:解析内嵌MSI数据库(适用属性不全的安装包)
如果方法1读取不到完整信息,可以调用Windows Installer COM对象解析安装包内嵌的MSI数据库获取完整属性:
$installerPath = "C:\下载路径\npp.8.1.7.Installer.x64.exe" $msiReadOnlyMode = 32 $installerCom = New-Object -ComObject WindowsInstaller.Installer # 打开安装包MSI数据库查询所需属性 $db = $installerCom.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $installerCom, @($installerPath, $msiReadOnlyMode)) $view = $db.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $db, @("SELECT `Value` FROM `Property` WHERE `Property` IN ('ProductName','ProductVersion','DisplayName')")) $view.GetType().InvokeMember("Execute", "InvokeMethod", $null, $view, $null) # 输出查询到的属性 while($record = $view.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $view, $null)) { $propName = $record.GetType().InvokeMember("StringData", "GetProperty", $null, $record, 1) $propValue = $record.GetType().InvokeMember("StringData", "GetProperty", $null, $record, 2) Write-Host "$propName : $propValue" } # 释放COM对象避免内存泄漏 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($installerCom) | Out-Null
版本比对逻辑实现
获取到安装包的产品名和版本后,可按以下逻辑和本地已安装程序比对,注意版本号需要转成[version]类型比对,避免字符串比对出现1.10判定为低于1.2的错误:
# 推荐使用注册表查询已安装程序,比Win32_Product速度快且不会触发MSI修复校验 $installedApps = @( Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | Where-Object {$_.DisplayName -and $_.DisplayVersion} | Select-Object DisplayName, DisplayVersion ) # 假设已从安装包获取到产品名$pkgName、版本号$pkgVersion $matchedApp = $installedApps | Where-Object {$_.DisplayName -eq $pkgName} | Select-Object -First 1 if ($matchedApp) { $installedVer = [version]$matchedApp.DisplayVersion $targetPkgVer = [version]$pkgVersion if ($targetPkgVer -gt $installedVer) { Write-Host "安装包版本更高,执行安装逻辑" # 此处补充安装命令 } else { Write-Host "已安装版本不低于安装包版本,跳过安装" } } else { Write-Host "未检测到已安装版本,直接执行安装" # 此处补充安装命令 }
内容的提问来源于stack exchange,提问作者davisoski
相关产品推荐
相关产品推荐

