我多年前编写了一个PC审计工具,并一直保持最新状态。其中一个基本功能是报告正在审核的PC上运行的Windows版本,我一直使用GetVersionEx调用。
这适用于Windows 8,但在Windows 10下不受支持,Windows 10确实像Windows 8一样返回8.2。 Microsoft似乎没有引入任何直接替代品,而是建议您检查所需的特定功能而不是查看操作系统,但出于审计的目的,我实际上需要操作系统名称。
'scanner'是一个C ++程序,必须在非特权帐户下运行,所以我不认为我读过另一个建议 - 拿起系统DLL的版本如kernel32.dll将起作用,因为这些文件夹通常无法访问给用户。
欢迎任何其他建议/想法!
GetVersion和GetVersionEx被various version helper functions取代。你想要的是IsWindows10OrGreater。它们可以在VersionHelpers.h中找到。
IsWindows10OrGreater仅在最新的SDK / Visual Studio 2015中提供。但是,您可以在一般情况下使用IsWindowsVersionOrGreater。例如,在我的7盒子上,我为IsWindowsVersionOrGreater(6,0,0)获得了TRUE。
请记住,此函数所使用的参数与Windows内部版本号和非市场营销名称相关。所以Windows 8是构建6.2。 Windows 7是6.0等
从Windows 8.1开始,GetVersion()
和GetVersionEx()
受申请表现限制:
随着Windows 8.1的发布,
GetVersionEx
API的行为已经改变了它将为操作系统版本返回的值。GetVersionEx
函数返回的值现在取决于应用程序的显示方式。未在Windows 8.1或Windows 10中显示的应用程序将返回Windows 8 OS版本值(6.2)。一旦应用程序显示给定的操作系统版本,
GetVersionEx
将始终返回应用程序在将来的版本中显示的版本。要显示Windows 8.1或Windows 10的应用程序,请参阅Targeting your application for Windows。
较新的Version Helper functions只是VerifyVersionInfo()
的包装纸。从Windows 10开始,它现在也受到表现:
Windows 10:如果设置
VerifyVersionInfo
参数以便指定Windows 8.1或Windows 10,即使当前操作系统版本为Windows 8.1或Windows 10.具体来说,lpVersionInfo
具有以下行为:
- 如果应用程序没有清单,则
VerifyVersionInfo
的行为就像操作系统版本是Windows 8(6.2)一样。- 如果应用程序的清单包含与Windows 8.1对应的GUID,则
VerifyVersionInfo
的行为就像操作系统版本是Windows 8.1(6.3)一样。- 如果应用程序的清单包含与Windows 10对应的GUID,则
VerifyVersionInfo
的行为就像操作系统版本是Windows 10(10.0)一样。
VerifyVersionInfo
使用Version Helper functions函数,因此行为VerifyVersionInfo
和IsWindows8Point1OrGreater
同样受到清单的存在和内容的影响。要显示Windows 8.1或Windows 10的应用程序,请参阅
IsWindows10OrGreater
。
为了获得真实的操作系统版本而不管表现形式,Microsoft建议查询系统DLL的文件版本:
Targeting your application for Windows
要获取操作系统的完整版本号,请在其中一个系统DLL(例如Getting the System Version)上调用
GetFileVersionInfo
函数,然后调用Kernel32.dll
以获取文件版本信息的VerQueryValue
子块。
另一种方法是使用\\StringFileInfo\\<lang><codepage>\\ProductVersion
,RtlGetVersion()
或NetServerGetInfo()
代替。他们都报告了一个准确的操作系统版本,并且不受表现(但是?)。
我需要这个在VS编译器的旧版本上工作,而在Qt框架中更多。这就是我如何实现这一目标的。
将此文件NetWkstaGetInfo()
添加到您的Qt项目:
GetWinVersion.h
在pro或pri qmake文件中添加所需的链接:
#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
像这样实现辅助函数(注意这里使用的SystemInfo是我的一个自定义类,但是你明白了......):
msvc: LIBS += -lKernel32
现在这是真正的关键。您需要将一个清单文件附加到您的exe文件中,该文件将“定位”最近的Windows版本,否则您无法检测到它们(请参阅MS文档:#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
...
)。以下是执行此操作的示例清单:
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>
理论上,您可以使用qmake运行附加清单的最后一位。我找到的例子没有运气,现在只是“欺骗”了这批...
使用以下功能:
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%"
它将Windows版本作为双精度返回(7,8,8.1,10)。