从注册表获取MSI安装参数:PowerShell恢复自定义MSI的参数难题
解决从注册表提取MSI安装参数的问题
我来帮你搞定这个MSI恢复时的参数难题——这确实是做自定义MSI快照与恢复工具时最容易卡壳的环节之一。结合我之前做类似工具的经验,给你分享两种可靠的方法:
方法一:从Uninstall注册表项提取参数
Windows会把已安装MSI的核心信息存在两个关键注册表路径(区分32/64位程序):
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*
大部分MSI会在这里存储卸载命令,而卸载命令里的参数往往和安装参数有重叠(比如静默安装参数、目标路径等)。你可以用PowerShell遍历这些路径,提取目标发布者的MSI参数:
# 替换为你的目标发布者名称 $targetPublisher = "Your Custom Publisher Name" # 覆盖32位和64位程序的注册表路径 $uninstallRegPaths = @( "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ) foreach ($regPath in $uninstallRegPaths) { Get-ItemProperty -Path $regPath | Where-Object { $_.Publisher -eq $targetPublisher -and $_.UninstallString -match "msiexec.exe" } | Select-Object DisplayName, Publisher, @{ Name = "ExtractedInstallArgs" Expression = { # 从卸载命令中剥离msiexec和MSI路径,提取剩余参数 $uninstallArgs = $_.UninstallString -replace 'msiexec\.exe\s+(/X|/x)\s+([^\s]+)\s*(.*)', '$3' # 如果卸载命令里没有参数,尝试从ModifyPath提取(部分MSI会在这里存安装相关参数) if ([string]::IsNullOrWhiteSpace($uninstallArgs) -and $_.ModifyPath) { $_.ModifyPath -replace 'msiexec\.exe\s+(/I|/i)\s+([^\s]+)\s*(.*)', '$3' } else { $uninstallArgs } } } }
方法二:直接从MSI数据库提取核心属性
如果注册表中没有存储完整的安装参数,你可以直接读取MSI文件本身的数据库——Windows Installer会把安装时的关键配置(比如目标路径、是否按用户安装等)存在MSI的Property表中。用PowerShell调用Windows Installer COM对象就能提取这些属性:
function Get-MsiCoreInstallProperties { param( [Parameter(Mandatory=$true)] [string]$MsiFilePath ) # 创建Windows Installer COM对象 $installer = New-Object -ComObject WindowsInstaller.Installer try { # 以只读模式打开MSI数据库 $database = $installer.OpenDatabase($MsiFilePath, 0) # 查询Property表中的关键安装属性 $view = $database.OpenView(@" SELECT Property, Value FROM Property WHERE Property IN ('ALLUSERS', 'INSTALLDIR', 'TARGETDIR', 'INSTALLLOCATION', 'ADDLOCAL') "@) $view.Execute() $installArgs = @() while ($record = $view.Fetch()) { $propName = $record.StringData(1) $propValue = $record.StringData(2) if ($propValue) { $installArgs += "/$propName=`"$propValue`"" } } return $installArgs -join " " } finally { # 清理COM对象,避免内存泄漏 if ($record) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($record) | Out-Null } if ($view) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($view) | Out-Null } if ($database) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($database) | Out-Null } if ($installer) { [System.Runtime.Interopservices.Marshal]::ReleaseComObject($installer) | Out-Null } [GC]::Collect() [GC]::WaitForPendingFinalizers() } } # 使用示例:传入你复制到本地的MSI路径 Get-MsiCoreInstallProperties -MsiFilePath "C:\Snapshots\YourCustom.msi"
额外注意事项
- 不是所有MSI都会存储完整的自定义安装参数(比如某些第三方包的特殊参数),如果遇到这种情况,你可以检查注册表中的
InstallSource路径,看看原始安装介质里有没有setup.ini或其他配置文件,里面可能会记录完整的安装命令。 - 恢复安装时,你可以把提取到的参数和
msiexec /i "Path\To\MSI.msi"结合使用,比如:msiexec /i "C:\Snapshots\YourCustom.msi" $extractedArgs /qn(/qn是静默安装参数,根据你的需求调整)。
内容的提问来源于stack exchange,提问作者Moerwald
相关产品推荐
相关产品推荐

