[英]Detecting Windows 10 version
我的目标是在我的代码中检测 Windows 10,它必须跨平台以及跨不同版本的 Windows(至少 7 及更高版本)工作。 Windows 提供了IsWindows10OrGreater()
来解决这个问题,但它还有另一个问题,这个函数在以前的 Windows 版本中不存在。
你会发现无数关于这个的博客和 SO 问题,以及像 this 和 getversion 等函数返回一些不同版本而不是正确版本的明显疯狂。
例如在我的机器上 - IsWindows10OrGreater()
方法无法编译(我必须安装 Win10 SDK),并且IsWindowsVersionOrGreater()
报告6
作为主要版本。
那么有没有一种理智的多版本方法可以解决这个问题?
检索真实操作系统版本的最直接方法是调用RtlGetVersion 。 这是GetVersionEx
和VerifyVersionInfo
调用的,但不使用兼容性垫片。
您可以使用 DDK(通过 #include <ntddk.h> 并从内核模式链接 NtosKrnl.lib,或从用户模式链接 ntdll.lib),或者使用运行时动态链接,如下面的代码片段所示:
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;
}
如果您需要其他信息,您可以传递RTL_OSVERSIONINFOEXW结构代替RTL_OSVERSIONINFOW结构(正确分配dwOSVersionInfoSize成员)。
即使没有附加清单,这也会在 Windows 10 上返回预期结果。
来自VersionHelpers.h
IsWindows10OrGreater()
文件VersionHelpers.h
随 Windows 10 SDK 一起提供,但它也适用于以前的版本。 只需将其复制到您的开发环境即可。
它只是一个仅标头定义的小库,它使用VerSetConditionMask
和VerifyVersionInfoW
函数,这两个函数自 Windows 2000 起在 WinAPI 中可用。
Upd如果您的源代码不能包含清单文件,您可以使用简单的技巧:只需使用GetFileVersionInfo
函数获取任何系统 dll 的版本,例如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, ¤tVersion) != 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;
}
// should work on all platforms from Windows XP to Windows 10
NTSTATUS(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW);
OSVERSIONINFOEXW osInfo;
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
if ( NULL != RtlGetVersion )
{
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
RtlGetVersion(&osInfo);
osInfo.dwMajorVersion;osInfo.dwMinorVersion; osInfo.dwBuildNumber;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.