You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让MSI API误认为指定UpgradeCode已安装?

嘿,帮你搞定Mock产品A的安装状态!

问题1:安装程序查询UpgradeCode的正确位置?

你提到的Win32_Property其实是单个MSI安装包文件的属性表哦,不是系统里记录已安装产品的地方。安装程序要检查A是否已安装,通常会从两个地方查:

  • 注册表:这是最常见的路径,64位系统下,64位程序看HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\{产品的ProductCode},32位程序则用HKLM\Software\Wow6432Node\...的路径。这个路径下的UpgradeCode值就是对应产品的升级代码。
  • WMI的Win32_Product类:这个类是Windows Installer维护的,里面的UpgradeCode属性对应已安装产品的升级代码,但它本质上也是从注册表和MSI数据库读取的,不是独立存储。

你说已经排除了注册表,可以再确认下是不是找对了32/64位的路径,或者安装程序确实用了WMI查询,但优先推荐先尝试注册表Mock,因为实现起来简单靠谱。


问题2:用PowerShell模拟A的UpgradeCode存在的实现方式

直接修改WMI的Win32_Product是行不通的,因为这个类是Windows Installer管的,不让手动创建或修改实例。最靠谱的方法是在注册表中造一个假的已安装产品条目,让B的安装程序误以为A已经装好了。

具体PowerShell脚本步骤:

我给你写了完整脚本,你只需要替换$targetUpgradeCode为你已知的A的UpgradeCode(格式要带大括号的GUID,比如"{12345678-ABCD-1234-ABCD-1234567890AB}")就行:

# 替换成你手头的产品A的UpgradeCode(必须是带大括号的GUID格式)
$targetUpgradeCode = "{你的A的UpgradeCode}"

# 生成一个随机的ProductCode(模拟已安装产品A的唯一标识,每个产品都要有独有的GUID)
$mockProductCode = [guid]::NewGuid().ToString("B")

# 根据系统位数选择对应的注册表路径,兼容32/64位程序
if ([Environment]::Is64BitOperatingSystem) {
    # 64位系统下,同时创建64位和32位路径的条目,确保不管B是32还是64位都能读到
    $uninstallPath64 = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    $uninstallPath32 = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    
    # 创建64位路径的注册表项
    if (-not (Test-Path $uninstallPath64)) {
        New-Item -Path $uninstallPath64 -Force | Out-Null
    }
    # 创建32位路径的注册表项
    if (-not (Test-Path $uninstallPath32)) {
        New-Item -Path $uninstallPath32 -Force | Out-Null
    }
    
    # 写入必要的注册表值(两个路径都写,避免遗漏)
    Set-ItemProperty -Path $uninstallPath64 -Name "UpgradeCode" -Value $targetUpgradeCode -Type String
    Set-ItemProperty -Path $uninstallPath64 -Name "DisplayName" -Value "Mocked Product A" -Type String
    Set-ItemProperty -Path $uninstallPath64 -Name "InstallDate" -Value (Get-Date -Format "yyyyMMdd") -Type String
    
    Set-ItemProperty -Path $uninstallPath32 -Name "UpgradeCode" -Value $targetUpgradeCode -Type String
    Set-ItemProperty -Path $uninstallPath32 -Name "DisplayName" -Value "Mocked Product A (32-bit)" -Type String
    Set-ItemProperty -Path $uninstallPath32 -Name "InstallDate" -Value (Get-Date -Format "yyyyMMdd") -Type String
} else {
    # 32位系统只用这个路径
    $uninstallPath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    if (-not (Test-Path $uninstallPath)) {
        New-Item -Path $uninstallPath -Force | Out-Null
    }
    Set-ItemProperty -Path $uninstallPath -Name "UpgradeCode" -Value $targetUpgradeCode -Type String
    Set-ItemProperty -Path $uninstallPath -Name "DisplayName" -Value "Mocked Product A" -Type String
    Set-ItemProperty -Path $uninstallPath -Name "InstallDate" -Value (Get-Date -Format "yyyyMMdd") -Type String
}

Write-Host "搞定!已经在注册表中Mock了产品A的UpgradeCode,模拟完成安装状态~"

测试后清理(可选):

测试完想删掉这个假条目?运行下面的脚本就行,记得把$mockProductCode替换成之前生成的那个GUID(或者你可以在第一个脚本里把这个GUID保存到文件里,方便后续清理):

$mockProductCode = "之前生成的ProductCode GUID"

if ([Environment]::Is64BitOperatingSystem) {
    $uninstallPath64 = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    $uninstallPath32 = "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    
    if (Test-Path $uninstallPath64) {
        Remove-Item -Path $uninstallPath64 -Recurse -Force
    }
    if (Test-Path $uninstallPath32) {
        Remove-Item -Path $uninstallPath32 -Recurse -Force
    }
} else {
    $uninstallPath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$mockProductCode"
    if (Test-Path $uninstallPath) {
        Remove-Item -Path $uninstallPath -Recurse -Force
    }
}

Write-Host "已清理Mock的产品A注册表条目,系统恢复原样啦~"

为啥这个方法管用?

绝大多数Windows Installer的安装程序在检查依赖时,都会优先读注册表的Uninstall条目,而不是调用复杂的WMI或MSI API。只要注册表中有带目标UpgradeCode的条目,安装程序就会认为对应的产品已经安装,直接跳过依赖检查。

如果真遇到只查WMI的安装程序,没关系——创建注册表条目后,WMI的Win32_Product类下次查询时会自动读取注册表的新内容,不需要额外操作。


内容的提问来源于stack exchange,提问作者PLB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:08:49