Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 检测Windows 10版本_C++_Windows_Winapi - Fatal编程技术网

C++ 检测Windows 10版本

C++ 检测Windows 10版本,c++,windows,winapi,C++,Windows,Winapi,我的目标是在我的代码中检测Windows 10,它必须跨平台以及不同版本的Windows(至少7及以上)工作。Windows提供了IsWindows10OrGreater()来解决此问题,但它还有另一个问题,此功能在以前的Windows版本中不存在 你会发现无数的博客和关于这一点的问题,以及像这个和getversion等函数返回不同版本而不是正确版本的显式疯狂 例如,在我的机器上,isWindows10OrCreater()方法无法编译(我必须安装Win10SDK),并且isWindowsVer

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

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

例如,在我的机器上,
isWindows10OrCreater()
方法无法编译(我必须安装Win10SDK),并且
isWindowsVersionOrCreater()
6
报告为主要版本

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

IsWindows10OrGreater()
from
VersionHelpers.h

请在查看注释

Windows 10 SDK附带了文件
VersionHelpers.h
,但它也适用于以前的版本。只需将其复制到您的开发环境中

它只是一个只定义了头的小库,它使用了
VerSetConditionMask
VerifyVersionInfo
函数,这两个函数自Windows 2000以来都在WinAPI中可用


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

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

您可以使用DDK(通过#包含并链接内核模式下的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;
}
如果需要其他信息,可以传递结构来代替结构(正确分配DWOSVersionInfo成员)

即使没有附加清单,也会在Windows 10上返回预期结果



另一方面,通常认为基于可用的功能而不是操作系统版本提供不同的实现是一种更好的解决方案。

您可以从注册表中读取实际版本号,然后从中推断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;
}
#包括
#包括
结构HKeyHolder
{
私人:
香港教育学院;
公众:
HKeyHolder():
m_键(空PTR)
{
}
HKeyHolder(const HKeyHolder&)=删除;
HKeyHolder&运算符=(常量HKeyHolder&)=删除;
~HKeyHolder()
{
如果(m_键!=nullptr)
RegCloseKey(m_键);
}
运算符HKEY()常量
{
返回m_键;
}
HKEY*操作员和()
{
返回&m_键;
}
};
布尔正在印度运行
{
HKeyHolder当前版本;
如果(RegOpenKeyExW(HKEY_本地_机器,LR“(软件\Microsoft\Windows NT\CurrentVersion)”,0,键\u查询值,&CurrentVersion)!=错误\u成功)
返回false;
DWORD值类型;
字节缓冲区[256];
DWORD bufferSize=256;
如果(RegQueryValueExW(currentVersion,L“CurrentBuild”,nullptr,和valueType,buffer,和bufferSize)!=错误\u成功)
返回false;
if(valueType!=REG_SZ)
返回false;
int版本;
std::wistringstream版本流(重新解释强制转换(缓冲区));
版本流>>版本;
返回版本>9800;
}

你为什么不安装Windows 10 SDK?嗯。。。不,你没有。只需定义
\u WIN32\u WINNT
/
WINVER
即可设置支持的最低目标操作系统。有关详细信息,请参阅。你可以使用Windows10SDK来瞄准WindowsVista。那么呢?只需使用Windows10SDK,然后继续前进。为什么您认为这不是一个解决方案?@IInspectable我的代码将在不同的应用程序之间共享,其中一些应用程序(开发人员)可能不会添加清单,并且许多VS 2015安装默认不包括win10 sdk—这是我发现此问题的方式。正如我所说,这不是一次性代码,它是在不同应用程序之间共享的库的一部分,其中一些将在windows 7、8或10下编译,为了分离我的逻辑,我必须检测10。@Barmak:它将编译,但要返回所需的结果,二进制文件需要相应的清单条目,其中说明:“现在看,我知道Windows 10已经存在,而且我已经做好了充分的准备。”根据MSDN的说法,最低限度的支持客户端是Windows 10本身。该应用程序将无法加载到以前的版本中。哦,男孩…“只需将其复制到您的开发环境中”…说真的吗?此外,
IsWindows10OrGreater()
未在Windows 8.1 SDK中声明(这并不奇怪)@hg_git您可以在不存在问题的地方搜索问题。只需从Windows SDK复制文件或添加安装Windows 10 SDK的要求即可使用源代码。仅此而已。@vladon:函数本身无法正常工作。您还必须提供清单,在编写库代码时无法强制执行。您不能“仅复制”"一个页眉。你不考虑可复制的构建环境吗?如果需要手动设置,它不是一个解决方案。除非有人遵循一些定制的指令,否则没有人能够建立。你不能这样做,并让它在任何开发者的系统上或在你的CI系统上工作。而且,你通过不规范而污染了你的构建环境;w您可能会在您的代码中引入依赖于您特殊自定义设置的假设。保持简单,不要做出如此仓促的更改。呃…如何检测功能支持?取决于功能。您要检测哪种功能?@Cu2S:取决于功能。如果某个功能作为新导出引入(例如),您可以
// 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;
}