我有一个安装程序,可以部署并运行单独的
.exe
文件以将驱动程序部署到系统。不幸的是,微软似乎在 Windows 10 及更高版本中放弃了对 VersionNT
宏的支持,所以我实现了另一篇文章中建议的方法:编写一个函数来查询 kernel32.dll
的版本号,并与哨兵进行比较价值(10.0.10240.16384
)。
这里有一个问题:当我直接从管理控制台运行此命令时,该命令可以正确检测我正在运行的 Windows 版本。
Current Windows Version: 10.0.10240.16384 - Cutoff Version: 10.0.10240.16384
但是,当该命令作为自定义操作从我的 WIX 工具集安装程序执行时,它似乎认为我正在使用旧版本的 Windows。此时我最好的猜测是安装程序或自定义操作命令在某种自动兼容模式下运行。
Current Windows Version: 6.2.10240.16384 - Cutoff Version: 10.0.10240.16384
我该如何继续?
VersionNT
的放弃确实令人沮丧,新版本的API(即:IsWindows10OrGreater()
)仅在Win10或更高版本上可用,因此在旧机器上我必须dlopen/dlsym
并测试故障。我不知道为什么创建一个简单的 int return_OS_Version(major, minor, release, revision,)
函数这么难。
还可以使用RegistrySearch检测Windows 10。例如,节点 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion 包含 CurrentBuild 和 CurrentBuildNumber 值。对于 Windows 8.1 或 Windows Server 2012R2,这些值为 9600,对于 Windows 10,它们很可能为 14393。
<Property Id="WINDOWSBUILDNUM" Secure="yes">
<RegistrySearch Id="YOUR_ID_HERE" Root="HKLM" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Name="CurrentBuild" Type="raw" />
</Property>
获得一个值后,可以像这样处理它,以便安装特定于 Windows 10 的文件:
<Component Id="YOUR_ID_HERE" Guid="YOUR_GUID_HERE" DiskId="1">
<Condition><![CDATA[Installed OR (WINDOWSBUILDNUM > 9999)]]></Condition>
<File Id="YOUR_ID_HERE" Name="Api.dll" Source="$(var.SolutionDir)\TheRestOfThePath\Api_for_win_10.dll"/>
</Component>
这有点像黑客(他们这样做,我们这样做......)但是绝望的时刻需要绝望的措施......
在 MSFT 玩的所有兼容性游戏中,它们似乎只掩盖了主要和次要,但掩盖了构建和修订。我还发现,在 Win8 上,他们将其掩盖为 6.2,在 Win 10 上,他们将其掩盖为 6.3。因此,我觉得这样做很舒服:
<Property Id="WIN10FOUND">
<DirectorySearch Id="searchSystem" Path="[SystemFolder]" Depth="0">
<FileSearch Id="searchFile" Name="advapi32.dll" MinVersion="6.3.10000.0"/>
</DirectorySearch>
</Property>
另一种方法可以是在自定义操作中以编程方式检测正确的 Windows 版本并设置属性。可以检查该房产的状况。
private static bool IsWindows10OrGreater()
{
Version ver = Environment.OSVersion.Version;
return ver.Major >= 10;
}
[CustomAction]
public static ActionResult SetWindowsVersion(Session session)
{
Version ver = Environment.OSVersion.Version;
session["OS_VERSION"] = ver.ToString();
// make Windows 10 as a default in case setting this property fails for some reason
session["IS_LESS_THAN_WIN10"] = !IsWindows10OrGreater() ? "1" : null;
return ActionResult.Success;
}