Wix Toolset 安装到 Program Files (x86) 解决指南
2025-03-07 09:26:39
Wix Toolset 创建的 MSI 安装到 Program Files (x86) 目录的解决办法
最近搞了个项目,用 Wix Toolset 打包成了 MSI 安装程序。 结果装完一看,程序跑 C:\Program Files (x86)
下面去了,可我明明需要它安装到C:\Program Files
。这可不行,得想办法解决!
问题原因分析
Windows 系统有两种不同的 "Program Files" 目录:
C:\Program Files
:用于 64 位应用程序。C:\Program Files (x86)
:用于 32 位应用程序。
安装程序默认安装到 C:\Program Files (x86)
,说明 Windows Installer 把它当成了 32 位程序。尽管我的程序文件本身(如上所示reslirp.exe
)确实是 x86-64 架构,但是安装包的配置出了差错,导致安装行为发生偏差。 这可能是 Wix 项目配置的问题,也可能是因为某些遗留的设置造成的。
解决方案
经过一番排查和实验,找到了以下几个需要注意的地方,逐一尝试和结合,最终可以解决安装路径问题:
1. 确保 Package 元素的属性设置
在 WiX v4 中, 不再使用Platform
属性。正确指定安装包目标平台,应该这么做:
-
删除不必要的属性: 首先检查你的
.wxs
文件, 确保 没有 任何Package/@Platform
属性. 如果有, 删除。 -
InstallerVersion
: 虽然和安装路径看似无关,但较旧的 Installer 版本可能行为有异。为了保险起见,Package/@InstallerVersion
设置成500
或更高. 这代表使用Windows Installer 5.0或更高版本, 对64位的支持更完善。 -
Scope
: 指定安装的范围。"perMachine" 表示为所有用户安装,这是安装到Program Files
的必要条件。如果设置成"perUser", 那就安装到用户目录去了。
修改后的 <Package>
元素大概是这样:
<Package Compressed="yes" InstallerVersion="500" Manufacturer="HappyRobotsLTD"
Name="reSLIRP" Scope="perMachine"
UpgradeCode="12345678-ABCD-0001-0001-250131143054" Version="1.1.0.0">
<!-- 移除了任何可能存在的 Platform 属性 -->
</Package>
2. 使用 StandardDirectory
的正确 ID
要让程序安装到 64 位程序的 Program Files,需要使用 ProgramFiles64Folder
这个预定义的目录 ID. 看你的原始代码,这部分是正确的:
<StandardDirectory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="reSLIRP">
<!-- ... -->
</Directory>
</StandardDirectory>
3. 仔细检查 Component
的 Bitness
属性
确保所有包含 64 位文件的 Component 都设置了 Bitness="always64"
。在你的例子里,你已经这么做了:
<Component Bitness="always64" Id="ProductComponent">
<File Id="MainExecutable" KeyPath="yes" Source="build\reslirp.exe"/>
</Component>
确保每个<Component>
都设置好 Bitness="always64"
。
4. 排查隐式 32 位组件 (重要!)
即使所有显式定义的组件都正确设置了 Bitness
,Wix Toolset 仍有可能自动生成 32 位的组件。
检查在 WiX 处理过程产生的文件:
使用 dark.exe 对msi文件进行反编译。查看wxs文件确定有没有隐藏的32位组件。
使用如下命令进行编译和链接,生成 MSI 安装包。
wix build reslirp.wxs -ext WixToolset.UI.wixext
检查生成的ProductComponent.wxs
等中间文件.
如果仍有地方将程序安装至错误位置, 可以进一步采用排除法,例如分别测试每一个dll。
最常见的原因是自定义操作(Custom Actions)。 如果你用了自定义操作,且这个操作是 32 位的,整个安装包就会被视为 32 位。检查.wxs
文件中有没有<CustomAction>
,确保他们也是 64 位的.
5. 强制使用64位注册表视图(进阶)
在某些极端情况下,即使上述步骤都做了, 程序仍然可能安装在错误的地方.这可能和注册表重定向有关. 在64位 Windows 上, 32 位和 64 位应用程序有不同的注册表视图.
可以在 Component
内部使用 RegistryKey
元素, 并通过 Win64="yes"
强制写入到 64 位注册表, 作为最后的尝试:
<Component Bitness="always64" Id="ProductComponent" >
<File Id="MainExecutable" KeyPath="yes" Source="build\reslirp.exe"/>
<RegistryKey Root="HKLM"
Key="Software\MyCompany\MyApplication"
Win64="yes">
<RegistryValue Type="string" Name="InstallDir" Value="[INSTALLFOLDER]" />
</RegistryKey>
</Component>
这会强制向 64 位注册表写入一个键值。但要注意, 随意修改注册表可能造成问题. 仅在必要时这样做,并确保清楚自己在做什么。而且写入一个用不着的注册表信息属于画蛇添足.通常不推荐这么做。
6. 检查构建环境
虽然不太可能,但为了完整起见,仍然值得确认下:
- 构建机器: 确保在 64 位 Windows 上构建。
- WiX 版本: 用比较新的 WiX Toolset 版本, 建议用 v4或更高。 可以通过
wix -version
来确认使用的 Wix Toolset 版本号。 - 清理并重建:
wix build -clean reslirp.wxs
,wix build reslirp.wxs -ext WixToolset.UI.wixext
. 彻底清理并重新构建项目。
如果用了持续集成 (CI) 系统, 也检查 CI 环境的配置。
通过以上的排查方法,修改和配置后重新编译构建,你的MSI安装程序就能够正确地安装到C:\Program Files
目录下。仔细排查配置,一定可以解决!