检测Windows 10版本

我的目标是检测我的代码中的Windows 10,它必须跨平台以及不同版本的Windows(至less7以上)工作。 Windows提供了IsWindows10OrGreater()来解决这个问题,但是还有另一个问题,这个函数在以前的Windows版本中不存在。

你会发现无数的博客和关于这个问题,以及明显的疯狂,这样的function和冒充和其他人返回一些不同的版本,而不是正确的。

例如,在我的机器上 – 方法IsWindows10OrGreater()不能编译(我将不得不安装Win10 SDK), IsWindowsVersionOrGreater()报告6作为主要版本。

那么有没有一个理智的多版本方式可以解决这个问题?

检索真正的操作系统版本最直接的方法是调用RtlGetVersion 。 这是GetVersionExVerifyVersionInfo调用的,但不使用兼容性垫片。

您可以使用DDK(通过#include <ntddk.h>并链接到NtosKrnl.lib),或使用运行时动态链接,如下面的代码片段所示:

 typedef LONG NTSTATUS, *PNTSTATUS; #define STATUS_SUCCESS (0x00000000) typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); RTL_OSVERSIONINFOW GetRealOSVersion() { HMODULE hMod = ::GetmoduleeHandleW(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; } 

如果您需要其他信息,则可以传递RTL_OSVERSIONINFOEXW结构来代替RTL_OSVERSIONINFOW结构(正确分配dwOSVersionInfoSize成员)。

这将返回Windows 10上的预期结果,即使没有附加清单。


另外,通常认为它是基于可用功能而不是OS版本提供不同实现的更好的解决方案。

VersionHelpers.h IsWindows10OrGreater()

检查在MSDN上的版本助手功能的笔记

文件VersionHelpers.h随Windows 10 SDK提供,但也可以在以前的版本中使用。 只要把它复制到你的开发环境。

它只是一个头文件定义的小型库,它使用VerSetConditionMaskVerifyVersionInfoW函数,这两个函数都可以在Windows 2000以后的WinAPI中使用。

Upd如果你不能在你的源代码中包含manifest文件,那么你可以使用简单的hack:只需要获取任何系统dll的一个版本,例如使用GetFileVersionInfo函数的kernel32.dll

您可以从注册表中读取真实的内部版本号,然后从中推断Windows版本。 您的应用程序不需要为此工作提供清单:在我的机器上,它正确地检测到操作系统内部版本号为10586.例如:

 #include <Windows.h> #include <sstream> struct HKeyHolder { private: HKEY m_Key; public: HKeyHolder() : m_Key(nullptr) { } HKeyHolder(const HKeyHolder&) = delete; HKeyHolder& operator=(const HKeyHolder&) = delete; ~HKeyHolder() { if (m_Key != nullptr) RegCloseKey(m_Key); } operator HKEY() const { return m_Key; } HKEY* operator&() { return &m_Key; } }; bool IsRunningOnWindows10() { HKeyHolder currentVersion; if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)", 0, KEY_QUERY_VALUE, &currentVersion) != ERROR_SUCCESS) return false; DWORD valueType; BYTE buffer[256]; DWORD bufferSize = 256; if (RegQueryValueExW(currentVersion, L"CurrentBuild", nullptr, &valueType, buffer, &bufferSize) != ERROR_SUCCESS) return false; if (valueType != REG_SZ) return false; int version; std::wistringstream versionStream(reinterpret_cast<wchar_t*>(buffer)); versionStream >> version; return version > 9800; }