Wix Installer:安装的服务启动时无法读取HKLM注册表项
解决Wix MSI安装服务后无法读取注册表的问题
咱们先从你的日志和描述里捋清楚核心问题:你用Wix 3.11制作的MSI确实已经把注册表项写入系统了,但服务启动时就是读不到这些键值;而手动写入相同注册表项后,服务就能正常运行——这大概率是Windows注册表重定向机制在搞鬼,也就是32位与64位程序的注册表路径不匹配导致的。
核心原因分析
从你的安装路径C:\Program Files (x86)\...能看出来,你的MSI是32位安装包。默认情况下,32位程序往HKLM\SOFTWARE写入数据时,Windows会自动将其重定向到HKLM\SOFTWARE\Wow6432Node这个32位专属注册表路径。
如果你的xpto-server.exe是64位程序,它读取HKLM\SOFTWARE\XPTOInc\...时,会直接访问64位注册表根路径,根本不会去Wow6432Node里查找,自然就找不到Wix写入的键值,服务启动失败也就成了必然结果。
具体解决方案
方案1:让Wix直接写入64位注册表(适合64位服务)
如果你的服务是64位程序,直接让Wix跳过注册表重定向,写入64位专属路径即可。只需要给注册表组件添加Win64="yes"属性,同时将Package元素指定为x64平台:
修改注册表组件代码:
<Component Id="CMP_RegistryEntries" Guid="xxxxxxxxx" Win64="yes"> <RegistryKey Root="HKLM" Key="SOFTWARE\XPTOInc\XPTO\XPTOServer\BetaVersion"> <RegistryValue Name="token" Action="write" Value="[TOKEN]" Type="string" KeyPath="yes" /> <RegistryValue Name="[IDENTIFIER_TYPE]" Action="write" Value="[INSTALLEDID]" Type="string" /> <RegistryValue Name="installDir" Action="write" Value="[INSTALLFOLDER]" Type="string" /> </RegistryKey> </Component>
修改Package元素代码:
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated" Platform="x64" />
方案2:修改服务代码适配注册表路径(适合32位服务)
如果你的服务是32位程序,它默认读取注册表时会被重定向到Wow6432Node,但如果代码里硬编码了64位路径,就会找不到键值。此时可以:
- 直接在代码里将注册表路径改为
HKLM\SOFTWARE\Wow6432Node\XPTOInc\XPTO\XPTOServer\BetaVersion; - 或者调用Windows API时添加
KEY_WOW64_64KEY(访问64位注册表)或KEY_WOW64_32KEY(访问32位注册表)标志,根据实际需求选择。
方案3:先定位注册表实际写入位置
你可以先打开注册表编辑器(regedit.exe),分别检查以下两个路径:
- 32位注册表路径:
HKLM\SOFTWARE\Wow6432Node\XPTOInc\XPTO\XPTOServer\BetaVersion - 64位注册表路径:
HKLM\SOFTWARE\XPTOInc\XPTO\XPTOServer\BetaVersion
看看Wix到底把键值写到了哪个位置,再对比服务代码里的读取路径,就能快速定位问题根源。
额外排查小技巧
- 虽然日志提示权限问题,但你手动写入注册表后服务能正常启动,说明权限不是核心问题,不过仍可确认下服务的登录账户是否有对应注册表路径的读取权限;
- 可以将服务的
Start属性改成demand(手动启动),安装完成后手动启动服务,同时用Process Monitor监控服务的注册表读取操作,能直观看到它在查找哪个路径; - 从日志来看,Custom Action返回的
TOKEN、INSTALLEDID等变量已经正确写入注册表,这部分无需怀疑。
内容的提问来源于stack exchange,提问作者Lucas Blaschi Gameiro
相关产品推荐
相关产品推荐

