C++ 如何检测 Windows 10
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32115255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ How to detect Windows 10
提问by user1169502
I have written a PC auditing tool many years ago and have been keeping it up to date. One of basic functions is reporting the version of Windows running on the PC being audited for which I have always used the GetVersionEx call.
多年前我编写了一个 PC 审计工具,并且一直在更新它。其中一项基本功能是报告正在审核的 PC 上运行的 Windows 版本,我一直使用 GetVersionEx 调用来获取这些版本。
This works up to and including Windows 8 but is not supported under Windows 10 and indeed Windows 10 returns 8.2 just as windows 8 does. Microsoft do not seem to have introduced anything as a direct replacement suggesting instead that you check for specific features required rather than looking at the OS but for the purpose of the audit I actually want the OS name.
这适用于并包括 Windows 8,但在 Windows 10 下不受支持,实际上 Windows 10 返回 8.2,就像 Windows 8 一样。微软似乎没有引入任何直接替代的东西,而是建议您检查所需的特定功能而不是查看操作系统,但出于审计的目的,我实际上想要操作系统名称。
The 'scanner' is a C++ program which must run under non-privileged accounts so I don't think another suggestion I have read - picking up the version of a system DLL such as kernel32.dll will work as these folders are typically not accessible to users.
“扫描仪”是一个 C++ 程序,它必须在非特权帐户下运行,所以我认为我读过的另一个建议不是 - 选择系统 DLL 的版本(例如 kernel32.dll)将起作用,因为这些文件夹通常无法访问给用户。
Any other suggestions/thoughts are most welcome!
任何其他建议/想法是最受欢迎的!
回答by Robinson
GetVersion and GetVersionEx were superseded by various version helper functions. The one you want is IsWindows10OrGreater. They can be found in VersionHelpers.h.
GetVersion 和 GetVersionEx 被各种版本辅助函数取代。您想要的是IsWindows10OrGreater。它们可以在VersionHelpers.h 中找到。
IsWindows10OrGreateris only available in the latest SDK/Visual Studio 2015. You can use IsWindowsVersionOrGreaterin the general case however. For example on my 7 box I get TRUE for IsWindowsVersionOrGreater(6, 0, 0).
IsWindows10OrGreater仅在最新的 SDK/Visual Studio 2015 中可用。但是,您可以在一般情况下使用IsWindowsVersionOrGreater。例如,在我的 7 盒子上,IsWindowsVersionOrGreater(6, 0, 0)为 TRUE 。
Remember that the parameters this function takes relate to Windows build number and NOT marketing name. So Windows 8 is build 6.2. Windows 7 is 6.0 etc.
请记住,此函数采用的参数与 Windows 内部版本号相关,而不是营销名称。所以 Windows 8 是 build 6.2。Windows 7 是 6.0 等。
回答by Remy Lebeau
Starting in Windows 8.1, GetVersion()
and GetVersionEx()
are subject to application manifestation:
从 Windows 8.1 开始,GetVersion()
并GetVersionEx()
受应用程序表现的约束:
With the release of Windows 8.1, the behavior of the
GetVersionEx
API has changed in the value it will return for the operating system version. The value returned by theGetVersionEx
function now depends on how the application is manifested.Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version,
GetVersionEx
will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10, refer to Targeting your application for Windows.
随着 Windows 8.1 的发布,
GetVersionEx
API的行为在它为操作系统版本返回的值方面发生了变化。函数返回的值GetVersionEx
现在取决于应用程序的显示方式。未针对 Windows 8.1 或 Windows 10 显示的应用程序将返回 Windows 8 操作系统版本值 (6.2)。一旦为给定的操作系统
GetVersionEx
版本显示应用程序,将始终返回应用程序在未来版本中显示的版本。要显示适用于 Windows 8.1 或 Windows 10的应用程序,请参阅面向 Windows 的应用程序。
The newer Version Helper functionsare simply wrappers for VerifyVersionInfo()
. Starting in Windows 10, it is now subject to manifestation as well:
较新的版本助手函数只是VerifyVersionInfo()
. 从 Windows 10 开始,它现在也有表现形式:
Windows 10:
VerifyVersionInfo
returns false when called by applications that do not have a compatibility manifest for Windows 8.1 or Windows 10 if thelpVersionInfo
parameter is set so that it specifies Windows 8.1 or Windows 10, even when the current operating system version is Windows 8.1 or Windows 10. Specifically,VerifyVersionInfo
has the following behavior:
- If the application has no manifest,
VerifyVersionInfo
behaves as if the operation system version is Windows 8 (6.2).- If the application has a manifest that contains the GUID that corresponds to Windows 8.1,
VerifyVersionInfo
behaves as if the operation system version is Windows 8.1 (6.3).- If the application has a manifest that contains the GUID that corresponds to Windows 10,
VerifyVersionInfo
behaves as if the operation system version is Windows 10 (10.0).The Version Helper functionsuse the
VerifyVersionInfo
function, so the behaviorIsWindows8Point1OrGreater
andIsWindows10OrGreater
are similarly affected by the presence and content of the manifest.To manifest your applications for Windows 8.1 or Windows 10, see Targeting your application for Windows.
Windows 10:
VerifyVersionInfo
如果该lpVersionInfo
参数设置为指定 Windows 8.1 或 Windows 10,即使当前操作系统版本是 Windows 8.1 或 Windows 10 ,当被没有 Windows 8.1 或 Windows 10 兼容性清单的应用程序调用时返回 false . 具体来说,VerifyVersionInfo
有以下行为:
- 如果应用程序没有清单,则
VerifyVersionInfo
表现为操作系统版本为 Windows 8 (6.2)。- 如果应用程序的清单包含对应于 Windows 8.1 的 GUID,
VerifyVersionInfo
则其行为就像操作系统版本是 Windows 8.1 (6.3)。- 如果应用程序的清单包含对应于 Windows 10 的 GUID,
VerifyVersionInfo
则其行为就像操作系统版本是 Windows 10 (10.0)。该版本助手功能使用
VerifyVersionInfo
功能,所以其行为IsWindows8Point1OrGreater
与IsWindows10OrGreater
同样受到清单的存在和内容。若要显示适用于 Windows 8.1 或 Windows 10的应用程序,请参阅面向 Windows 的应用程序。
To get the trueOS version regardless of manifestation, Microsoft suggests querying the file version of a system DLL:
为了获得真实的操作系统版本,无论表现如何,微软建议查询系统 DLL 的文件版本:
To obtain the full version number for the operating system, call the
GetFileVersionInfo
function on one of the system DLLs, such asKernel32.dll
, then callVerQueryValue
to obtain the\\StringFileInfo\\<lang><codepage>\\ProductVersion
subblock of the file version information.
要获取操作系统的完整版本号,请在
GetFileVersionInfo
系统 DLL 之一上调用该函数,例如Kernel32.dll
,然后调用VerQueryValue
以获取\\StringFileInfo\\<lang><codepage>\\ProductVersion
文件版本信息的子块。
Another way is to use RtlGetVersion()
, NetServerGetInfo()
, or NetWkstaGetInfo()
instead. They all report an accurate OS version and are not subject to manifestation (yet?).
另一种方法是使用RtlGetVersion()
, NetServerGetInfo()
, 或NetWkstaGetInfo()
代替。它们都报告了准确的操作系统版本,并且不受表现形式的影响(还没有?)。
回答by Michael Haephrati
Use the following function:
使用以下函数:
double getSysOpType()
{
int ret = 0.0;
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
OSVERSIONINFOEXW osInfo;
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
if (NULL != RtlGetVersion)
{
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
RtlGetVersion(&osInfo);
ret = osInfo.dwMajorVersion;
}
return ret;
}
It will return the Windows version as a double (7, 8, 8.1, 10).
它将以双精度形式返回 Windows 版本(7、8、8.1、10)。
回答by BuvinJ
I needed this to work on an older version of the VS compiler, and more over within a Qt framework. Here's how I accomplished that.
我需要它来处理旧版本的 VS 编译器,以及在 Qt 框架中的更多内容。这是我如何做到的。
Add this file GetWinVersion.h
to your Qt project:
将此文件添加GetWinVersion.h
到您的 Qt 项目中:
#ifndef GETWINVERSION
#define GETWINVERSION
#include <QtGlobal>
#ifdef Q_OS_WIN
#include <windows.h>
#include <stdio.h>
float GetWinVersion()
{
OSVERSIONINFO osvi;
ZeroMemory( &osvi, sizeof(OSVERSIONINFO) );
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
return GetVersionEx( &osvi ) ?
(float)osvi.dwMajorVersion +
((float)osvi.dwMinorVersion/10) :
0.0 ;
}
#endif //Q_OS_WIN
#endif // GETWINVERSION
Add the required linkage in your pro or pri qmake file:
在您的 pro 或 pri qmake 文件中添加所需的链接:
msvc: LIBS += -lKernel32
Implement the helper function like so (note SystemInfo used here is a custom class of mine, but you get the idea...):
像这样实现辅助函数(注意这里使用的 SystemInfo 是我的自定义类,但你明白了......):
#include "GetWinVersion.h"
SystemInfo info;
#ifdef Q_OS_WIN
info.setPlatform( SystemInfo::WINDOWS );
switch(QSysInfo::windowsVersion())
{
case QSysInfo::WV_32s: info.setOsName( L"3.1" ); info.setOsVersion( 3.1 ); break;
case QSysInfo::WV_95: info.setOsName( L"95" ); info.setOsVersion( 4.0 ); break;
case QSysInfo::WV_98: info.setOsName( L"98" ); info.setOsVersion( 4.1 ); break;
case QSysInfo::WV_Me: info.setOsName( L"Me" ); info.setOsVersion( 4.9 ); break;
case QSysInfo::WV_NT: info.setOsName( L"NT" ); info.setOsVersion( 4.0 ); break;
case QSysInfo::WV_2000: info.setOsName( L"2000" ); info.setOsVersion( 5.0 ); break;
case QSysInfo::WV_XP: info.setOsName( L"XP" ); info.setOsVersion( 5.1 ); break;
case QSysInfo::WV_2003: info.setOsName( L"2003" ); info.setOsVersion( 5.2 ); break; // Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition
case QSysInfo::WV_VISTA: info.setOsName( L"Vista" ); info.setOsVersion( 6.0 ); break; // Windows Vista, Windows Server 2008
case QSysInfo::WV_WINDOWS7: info.setOsName( L"7" ); info.setOsVersion( 6.1 ); break; // Windows 7, Windows Server 2008 R2
case QSysInfo::WV_WINDOWS8: info.setOsName( L"8" ); info.setOsVersion( 6.2 ); break; // Windows 8, Windows Server 2012
// These cases are never reached due to Windows api changes
// As of Qt 5.5, this not accounted for by QSysInfo::windowsVersion()
//case QSysInfo::WV_WINDOWS8_1: info.setOsName( L"8.1" ); info.setOsVersion( 6.3 ); break; // Windows 8.1, Windows Server 2012 R2
//case QSysInfo::WV_WINDOWS10: info.setOsName( L"10" ); info.setOsVersion( 10.0 ); break; // Windows 10, Windows Server 2016
default:
// On Windows 8.1 & 10, this will only work when the exe
// contains a manifest which targets the specific OS's
// you wish to detect. Else 6.2 (ie. Win 8.0 is returned)
info.setOsVersion( GetWinVersion() );
if( info.osVersion() == 6.3f ) // Windows 8.1, Windows Server 2012 R2
info.setOsName( L"8.1" );
else if( info.osVersion() == 10.0f ) // Windows 10, Windows Server 2016
info.setOsName( L"10" );
else
info.setOsName( L"UNKNOWN" );
}
info.setOsBits( IsWow64() ? 64 : 32 );
#else
...
Now here's the real key. You need to attach a manifest file to your exe which will "target" the recent Windows versions, else you can't detect them (see the MS docs: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451%28v=vs.85%29.aspx). Here's an example manifest to do this:
现在这是真正的关键。您需要将清单文件附加到您的 exe 文件,该文件将“针对”最近的 Windows 版本,否则您无法检测到它们(请参阅 MS 文档:https: //msdn.microsoft.com/en-us/library/windows /desktop/ms724451%28v=vs.85%29.aspx)。这是执行此操作的示例清单:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="MyOrg.MyDept.MyAppName"
version="1.0.0.0"
processorArchitecture="x86"
type="win32" />
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>
And here's some batch to attach the manifest:
这是一些附加清单的批处理:
set exeFile=MyApp.exe
set manifestFile=MyApp.manifest
set manifestExe=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\x64\mt.exe
"%manifestExe%" -manifest "%manifestFile%" -outputresource:"%exeFile%"
In theory, you can use qmake to run that last bit attaching the manifest. I didn't have luck with the examples I found, and just "cheated" with this batch for now...
理论上,您可以使用 qmake 来运行附加清单的最后一点。我发现的例子并不走运,现在只是“欺骗”了这批……