Microsoft 于 2018 年 10 月 2 日发布了 Windows Server 2019。从 Windows 2000 到此 Windows 版本,您可以调用 WinAPI 函数 GetVersionEx结构 OSVERSIONINFOEX并根据dwMajorVersion
、dwMinorVersion
和wProductType
变量确定Windows版本,例如Windows 8.1、Windows 10、Windows Server 2012 R2。大家使用的代码是这样的:
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 functions没有检测 Server 2019 的功能。另外,奇怪的是关于 Targeting 的文档页面止于 Windows 10,不讨论服务器版本,而这些 Targeting list 对于检测 Windows 8.1 或 Server 2012 以上的操作系统是强制性的。
更新 1.
正如@IInspectable 和@RbMm 对 RtlGetVersion
函数的用法的评论。所以我运行了以下代码(取自 this answer ):
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
Windows 服务器 2019:
- dwMajorVersion = 10
- dwMinorVersion = 0
- dwBuildNumber = 17763
- dwPlatformId = 2
Update2. 根据要求,发布来自 OSVERSIONINFOEX 结构的完整信息,该结构是通过 GetVersionEx 调用获得的, list 文件包含所有目标,直到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. 使用结构 RTL_OSVERSIONINFOEXW
调用 RtlGetVersion
我们得到与更新 2 中完全相同的结果。
最佳答案
根据 Windows Server 2019 version info 中的讨论:
[Windows] Server 2019 Datacenter Edition build 17744, the ReleaseId field shows 1809.
所以像这样的东西应该可以解决问题:
const auto isWinServer2019Plus =
IsWindowsServer() &&
IsWindowsVersionOrGreater(10, 0, 1803);
关于C++ 如何检测 Windows Server 2019?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53393150/