如何在Wix安装包中阻止ARM/ARM64安装不兼容的键盘驱动?
我正在开发一款基于MSKLC的键盘布局驱动安装程序,这类驱动具有架构特异性,需阻止用户在不兼容计算机上安装。
此前仅涉及x86、x64和Itanium架构时,检测相对简单。在wxs文件中使用如下代码块即可:
<?if $(sys.BUILDARCH) = x86 ?> <Condition Message="!(loc.UnsupportedPlatformMessage)">Not Msix64</Condition> <Condition Message="!(loc.UnsupportedPlatformMessage)">Not Intel64</Condition> <?endif ?>
该代码可阻止x86版本在x64和Itanium平台安装,后两者的安装程序也会因兼容性缺失自动在x86及彼此平台安装失败。
但加入ARM和ARM64架构后,情况变复杂:Windows Installer未定义可检测的ARM专属属性,且ARM64系统支持x86和x64模拟。上述代码仍能让x86安装包提前失败,但找不到简单方法阻止x64安装包在ARM64平台安装。
我目前编写了如下代码块,并在LaunchConditions检查前调用ResolveCpuArchitecture自定义动作:
<?if $(sys.BUILDARCH) = x86 ?> <Property Id="TargetArchitecture" Value="X86" /> <Launch Condition="NOT VersionNT64" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = x64 ?> <Property Id="TargetArchitecture" Value="AMD64" /> <?endif?> <?if $(sys.BUILDARCH) = arm64 ?> <Property Id="TargetArchitecture" Value="ARM64" /> <?endif?> <Launch Condition="CpuArchitecture=TargetArchitecture" Message="!(loc.UnsupportedPlatformMessage)" /> <CustomAction Id="ResolveCpuArchitecture" Property="CpuArchitecture" Value="[%PROCESSOR_ARCHITECTURE]" />
但该方案不够优雅,且不确定是否按预期工作(目前ARM64安装包安装失败,原因不明),请问是否有更优实现方案?
方案1:利用环境变量区分真实与模拟架构
ARM64系统运行x64/x86程序时,PROCESSOR_ARCHITECTURE返回模拟架构值,但PROCESSOR_ARCHITEW6432会返回真实的ARM64。通过注册表读取这两个变量组合判断真实架构,无需自定义动作:
<!-- 读取真实架构属性 --> <Property Id="REAL_CPU_ARCHITECTURE"> <RegistrySearch Id="FindRealArch" Root="HKLM" Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment" Name="PROCESSOR_ARCHITEW6432" Type="raw" /> </Property> <!-- 无PROCESSOR_ARCHITEW6432时,直接使用PROCESSOR_ARCHITECTURE --> <SetProperty Id="REAL_CPU_ARCHITECTURE" Value="[%PROCESSOR_ARCHITECTURE]" After="AppSearch">NOT REAL_CPU_ARCHITECTURE</SetProperty> <!-- 分架构设置启动条件 --> <?if $(sys.BUILDARCH) = x86 ?> <LaunchCondition Condition="REAL_CPU_ARCHITECTURE = "X86" OR NOT VersionNT64" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = x64 ?> <LaunchCondition Condition="REAL_CPU_ARCHITECTURE = "AMD64"" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = arm64 ?> <LaunchCondition Condition="REAL_CPU_ARCHITECTURE = "ARM64"" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?>
方案2:使用Wix UtilExtension获取真实架构
Wix的UtilExtension提供GetWindowsVersion动作,可获取包含真实架构的WindowsVersion.Platform属性,值对应X86/X64/ARM/ARM64。
首先引入扩展:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
然后添加动作和条件:
<CustomActionRef Id="WixGetWindowsVersion" /> <?if $(sys.BUILDARCH) = x86 ?> <LaunchCondition Condition="WindowsVersion.Platform = "X86"" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = x64 ?> <LaunchCondition Condition="WindowsVersion.Platform = "X64"" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = arm64 ?> <LaunchCondition Condition="WindowsVersion.Platform = "ARM64"" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?>
方案3:修复原有自定义动作的执行逻辑
若坚持使用原有方案,需调整动作执行顺序并修正架构检测逻辑:
<!-- 确保自定义动作在LaunchConditions前执行 --> <InstallExecuteSequence> <Custom Action="ResolveCpuArchitecture" Before="LaunchConditions" /> </InstallExecuteSequence> <InstallUISequence> <Custom Action="ResolveCpuArchitecture" Before="LaunchConditions" /> </InstallUISequence> <?if $(sys.BUILDARCH) = x86 ?> <Property Id="TargetArchitecture" Value="X86" /> <LaunchCondition Condition="CpuArchitecture = TargetArchitecture OR NOT VersionNT64" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = x64 ?> <Property Id="TargetArchitecture" Value="AMD64" /> <LaunchCondition Condition="CpuArchitecture = TargetArchitecture" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <?if $(sys.BUILDARCH) = arm64 ?> <Property Id="TargetArchitecture" Value="ARM64" /> <LaunchCondition Condition="CpuArchitecture = TargetArchitecture" Message="!(loc.UnsupportedPlatformMessage)" /> <?endif?> <!-- 优先读取真实架构,不存在则回退 --> <CustomAction Id="ResolveCpuArchitecture" Property="CpuArchitecture" Value="[%PROCESSOR_ARCHITEW6432]" /> <SetProperty Id="CpuArchitecture" Value="[%PROCESSOR_ARCHITECTURE]" After="ResolveCpuArchitecture">NOT CpuArchitecture</SetProperty>
内容的提问来源于stack exchange,提问作者Rimas Kudelis

