c++ - C++ 如何检测 Windows Server 2019?
问题描述
Microsoft 于 2018 年 10 月 2 日发布了 Windows Server 2019。从 Windows 2000 到此 Windows 版本,您可以使用 struct OSVERSIONINFOEX并根据 的变量调用 WinAPI 函数GetVersionEx,并确定 Windows 版本,例如 Windows 8.1, Windows 10、Windows Server 2012 R2。大家使用的代码是这样的:dwMajorVersion
dwMinorVersion
wProductType
OSVERSIONINFOEX osvi;
SecureZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (GetVersionEx(&osvi)) {
if (osvi.dwMajorVersion == 10 &&
osvi.dwMinorVersion == 0 &&
osvi.wProductType != VER_NT_WORKSTATION) {
Console->Log("We are running on Windows Server 2016");
}
}
从Wikipedia来看, Windows Server 2019 的 NT 10.0 版本号与 Server 2016 相同。所以上面的代码不再起作用。
此外,Microsoft Docs 包含以下注释:GetVersionEx 可能会更改或无法用于 Windows 8.1 之后的版本。相反,请使用 Version Helper 函数。
不幸的是,Version Helper 函数没有检测 Server 2019 的功能。另外,奇怪的是关于Targeting的 Docs 页面在 Windows 10 停止,并且没有谈论 Server 版本,而这些 Targeting manifests 是检测操作系统所必需的高于 Windows 8.1 或 Server 2012。
更新 1.
正如 @IInspectable 和 @RbMm 评论了RtlGetVersion
函数的使用。所以我运行了以下代码(取自这个答案):
typedef LONG NTSTATUS, *PNTSTATUS;
#define STATUS_SUCCESS (0x00000000)
typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
RTL_OSVERSIONINFOW GetRealOSVersion() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (fxPtr != nullptr) {
RTL_OSVERSIONINFOW rovi = { 0 };
rovi.dwOSVersionInfoSize = sizeof(rovi);
if ( STATUS_SUCCESS == fxPtr(&rovi) ) {
return rovi;
}
}
}
RTL_OSVERSIONINFOW rovi = { 0 };
return rovi;
}
以下是Windows 10的结果:
- dwMajorVersion = 10
- dwMinorVersion = 0
- dwBuildNumber = 17134
- dwPlatformId = 2
视窗服务器 2019:
- dwMajorVersion = 10
- dwMinorVersion = 0
- dwBuildNumber = 17763
- dwPlatformId = 2
更新2。根据要求,发布从通过GetVersionEx调用获得的OSVERSIONINFOEX结构的完整信息,其中包含直到 Windows 10 的所有目标的清单文件(请参阅上面的目标链接):
// Windows 10
osvi.dwOSVersionInfoSize = 284
osvi.dwMajorVersion = 10
osvi.dwMinorVersion = 0
osvi.dwBuildNumber = 17134
osvi.dwPlatformId = 2
osvi.szCSDVersion =
osvi.wServicePackMinor = 0
osvi.wServicePackMinor = 0
osvi.wSuiteMask = 256 // 0x100
osvi.wProductType = 1
osvi.wReserved = 0
// Windows Server 2016
osvi.dwOSVersionInfoSize = 284
osvi.dwMajorVersion = 10
osvi.dwMinorVersion = 0
osvi.dwBuildNumber = 14393
osvi.dwPlatformId = 2
osvi.szCSDVersion =
osvi.wServicePackMinor = 0
osvi.wServicePackMinor = 0
osvi.wSuiteMask = 400
osvi.wProductType = 3
osvi.wReserved = 0
// Windows Server 2019
osvi.dwOSVersionInfoSize = 284
osvi.dwMajorVersion = 10
osvi.dwMinorVersion = 0
osvi.dwBuildNumber = 17763
osvi.dwPlatformId = 2
osvi.szCSDVersion =
osvi.wServicePackMinor = 0
osvi.wServicePackMinor = 0
osvi.wSuiteMask = 400 // 0x190
osvi.wProductType = 3
osvi.wReserved = 0
更新 3.RtlGetVersion
使用结构调用RTL_OSVERSIONINFOEXW
我们得到与更新 2 完全相同的结果。
解决方案
根据Windows Server 2019 版本信息中的讨论:
[Windows] Server 2019 Datacenter Edition build 17744,ReleaseId 字段显示 1809。
所以这样的事情应该可以解决问题:
const auto isWinServer2019Plus =
IsWindowsServer() &&
IsWindowsVersionOrGreater(10, 0, 1803);
推荐阅读
- javascript - 我需要在 forEach 中调用 api 并将这些响应放入一个数组并返回。但它在 js(javascript) 中作为空数组返回
- java - 为什么没有打印正确的数组值?
- python - 在微调变压器中无法获取锁(缓存文件)错误
- python - 使用 python 的上下文管理器获取上下文中的操作顺序
- excel-formula - SUMIFS - 使用单元格作为标准时没有给出值
- android - 如何用对象的真实比例绘制一个矩形?
- android - 为什么 Android Activity 在 24/7 工作 3 周后出现黑屏?
- asp.net-core - Asp.net 核心 Microsoft OIDC 库 OnAuthorizedCode 收到事件被触发两次
- python - 如何将一个数据帧分成几个数据帧
- mongodb - 如何更新 MongoDB 中的嵌套对象属性