安装后注册表中找不到WiX Product元素的UpgradeCode问题咨询
问题分析与解决
为什么注册表中找不到原始UpgradeCode?
Windows Installer不会直接以原始格式存储UpgradeCode,而是会对GUID做格式转换后再写入注册表:
- 去掉GUID的大括号
{},将所有字母转为小写 - 反转GUID的第一段(前8个字符),其余部分保持顺序不变
- 转换后的字符串作为注册表项名称,存放在对应路径下
举个例子:
原始UpgradeCode:{12345678-1234-1234-1234-1234567890AB}
转换后:87654321432143214321ba0987654321
另外注意64位系统的兼容性:
- 32位MSI的UpgradeCode会存放在
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes\下 - 64位MSI则直接存放在
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes\
如何通过UpgradeCode检测产品是否已安装?
1. 使用Windows Installer API(推荐)
调用MsiEnumRelatedProducts函数,直接传入原始UpgradeCode(带大括号),函数会自动处理格式转换,返回所有关联的已安装产品的ProductCode。这是最可靠的方法,避免手动处理注册表的麻烦。
2. PowerShell脚本实现
可以通过PowerShell调用Windows Installer API,示例代码:
$upgradeCode = "{MY-GUID}" # 替换为你的原始UpgradeCode $type = @" using System; using System.Runtime.InteropServices; public class MSIHelper { [DllImport("msi.dll", CharSet = CharSet.Unicode)] public static extern uint MsiEnumRelatedProducts(string szUpgradeCode, uint dwReserved, uint iProductIndex, StringBuilder lpProductBuf); } "@ Add-Type -TypeDefinition $type $productCode = New-Object System.Text.StringBuilder(39) $index = 0 while ($true) { $result = [MSIHelper]::MsiEnumRelatedProducts($upgradeCode, 0, $index, $productCode) if ($result -eq 0) { Write-Host "找到已安装产品:$($productCode.ToString())" $index++ $productCode.Clear() | Out-Null } else { break } }
3. 手动验证注册表
如果需要手动查找,按照以下步骤转换UpgradeCode:
- 去掉大括号,转小写:比如原始
{ABC123DE-FGHI-JKLM-NOPQ-RSTUVWXYZ123}处理后为abc123de-fghi-jklm-nopq-rstuvwxyz123 - 拆分第一段
abc123de并反转,得到ed321cba - 拼接剩余部分(去掉分隔符),最终得到
ed321cbafghijklmnopqrstuvwxyz123 - 到对应的UpgradeCodes路径下查找这个字符串命名的注册表项
内容的提问来源于stack exchange,提问作者Tiger Galo
相关产品推荐
相关产品推荐

