繁体   English   中英

检测 Windows 10 版本

[英]Detecting Windows 10 version

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

你会发现无数关于这个的博客和 SO 问题,以及像 this 和 getversion 等函数返回一些不同版本而不是正确版本的明显疯狂。

例如在我的机器上 - IsWindows10OrGreater()方法无法编译(我必须安装 Win10 SDK),并且IsWindowsVersionOrGreater()报告6作为主要版本。

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

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

您可以使用 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()

查看MSDN版本助手功能的注释

文件VersionHelpers.h随 Windows 10 SDK 一起提供,但它也适用于以前的版本。 只需将其复制到您的开发环境即可。

它只是一个仅标头定义的小库,它使用VerSetConditionMaskVerifyVersionInfoW函数,这两个函数自 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, &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;
}
// 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM