多年前,我已经编写了一个PC审核工具,并且一直在更新它。其中一个基本功能是报告正在审核的PC上运行的Windows版本,我一直使用GetVersionEx调用。
这适用于Windows 8,但在Windows 10下不受支持,Windows 10确实像Windows 8一样返回8.2。 Microsoft似乎没有引入任何直接替代品,而是建议您检查所需的特定功能而不是查看操作系统,但出于审计的目的,我实际上需要操作系统名称。
'扫描仪'是一个必须在非特权帐户下运行的C ++程序,所以我不会想到我读过的另一个建议 - 获取系统DLL的版本(例如kernel32.dll)将起作用,因为用户通常无法访问这些文件夹
欢迎任何其他建议/想法!
答案 0 :(得分:14)
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等。
答案 1 :(得分:12)
从Windows 8.1开始,GetVersion()
和GetVersionEx()
受申请表现限制:
随着Windows 8.1的发布,
GetVersionEx
API的行为已更改为操作系统版本返回的值。GetVersionEx
函数返回的值现在取决于应用程序的显示方式。未在Windows 8.1或Windows 10中显示的应用程序将返回Windows 8操作系统版本值(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兼容性清单的应用程序调用时返回false,如果lpVersionInfo
参数设置为指定Windows 8.1或Windows 10,即使当前操作系统版本是Windows 8.1或Windows 10.具体而言,VerifyVersionInfo
具有以下行为:
- 如果应用程序没有清单,
VerifyVersionInfo
的行为就像操作系统版本是Windows 8(6.2)一样。- 如果应用程序的清单包含与Windows 8.1对应的GUID,则
VerifyVersionInfo
的行为就像操作系统版本是Windows 8.1(6.3)一样。- 如果应用程序的清单包含与Windows 10对应的GUID,则
VerifyVersionInfo
的行为就像操作系统版本是Windows 10(10.0)一样。Version Helper functions使用
VerifyVersionInfo
函数,因此行为IsWindows8Point1OrGreater
和IsWindows10OrGreater
同样会受到清单的存在和内容的影响。要显示Windows 8.1或Windows 10的应用程序,请参阅Targeting your application for Windows。
要获得 true 操作系统版本而不管显示,Microsoft建议查询系统DLL的文件版本:
要获取操作系统的完整版本号,请调用其中一个系统DLL上的
GetFileVersionInfo
函数,例如Kernel32.dll
,然后调用VerQueryValue
以获取{{1}文件版本信息的子块。
另一种方法是使用RtlGetVersion()
,NetServerGetInfo()
或NetWkstaGetInfo()
代替。他们都报告了一个准确的操作系统版本,并且不受表现(但是?)。
答案 2 :(得分:1)
我需要这个来处理旧版本的VS编译器,而且更需要在Qt框架内工作。以下是我如何实现这一目标。
将此文件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
在pro或pri qmake文件中添加所需的链接:
msvc: LIBS += -lKernel32
实现类似的辅助函数(注意这里使用的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
...
现在,这是真正的关键。您需要将一个清单文件附加到您的exe文件中,该文件将“#34; target&#34;最新的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>
这里有一些批量附加清单:
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%"
理论上,您可以使用qmake运行附加清单的最后一位。我找到的例子并没有运气,只是被骗了#34;现在这个批次......
答案 3 :(得分:1)
使用以下功能:
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;
}
它将返回Windows版本为双精度(7、8、8.1、10)。
答案 4 :(得分:1)
#include <iostream>
#include <windows.h>
#pragma comment(lib, "Version.lib" )
BOOL GetOsVersion()
{
wchar_t path[200] = L"C:\\Windows\\System32\\kernel32.dll";
DWORD dwDummy;
DWORD dwFVISize = GetFileVersionInfoSize(path, &dwDummy);
LPBYTE lpVersionInfo = new BYTE[dwFVISize];
if (GetFileVersionInfo(path, 0, dwFVISize, lpVersionInfo) == 0)
{
return FALSE;
}
UINT uLen;
VS_FIXEDFILEINFO* lpFfi;
BOOL bVer = VerQueryValue(lpVersionInfo, L"\\", (LPVOID*)&lpFfi, &uLen);
if (!bVer || uLen == 0)
{
return FALSE;
}
DWORD dwProductVersionMS = lpFfi->dwProductVersionMS;
if (HIWORD(dwProductVersionMS) == 10 && LOWORD(dwProductVersionMS) == 0)
{
cout << "this is windows 10\n";
}
else if (HIWORD(dwProductVersionMS) == 6 && LOWORD(dwProductVersionMS) == 3)
{
cout << "this is windows 8.1\n";
}
else if (HIWORD(dwProductVersionMS) == 6 && LOWORD(dwProductVersionMS) == 2)
{
cout << "this is windows 8\n";
}
else if (HIWORD(dwProductVersionMS) == 6 && LOWORD(dwProductVersionMS) == 1)
{
cout << "this is windows 7 or Windows Server 2008 R2\n";
}
else if (HIWORD(dwProductVersionMS) == 6 && LOWORD(dwProductVersionMS) == 0)
{
cout << "this is windows Vista or Windows Server 2008\n";
}
else if (HIWORD(dwProductVersionMS) == 5 && LOWORD(dwProductVersionMS) == 2)
{
cout << "this is windows Server 2003\n";
}
else if (HIWORD(dwProductVersionMS) == 5 && LOWORD(dwProductVersionMS) == 1)
{
cout << "this is windows Server XP\n";
}
else if (HIWORD(dwProductVersionMS) == 5 && LOWORD(dwProductVersionMS) == 0)
{
cout << "this is windows 2000\n";
}
//else if (lpFfi->dwFileVersionMS == 4 && lpFfi->dwFileVersionLS == 90)
//{
// cout << "this is windows Me\n";
//}
//else if (lpFfi->dwFileVersionMS == 4 && lpFfi->dwFileVersionLS == 10)
//{
// cout << "this is windows 98\n";
//}
//else if (lpFfi->dwFileVersionMS == 4 && lpFfi->dwFileVersionLS == 0)
//{
// cout << "this is windows 95\n";
//}
return TRUE;
}
测试用于检测win10的代码后。
我推测此api错误IsWindows10OrGreater是因为为kernel32.dll设置了错误的FileVersionMS版本。使用ProductVersionMS版本查询可以正常获取它。
希望它可以帮助所有人!
答案 5 :(得分:0)
VersionHelpers.h
!有问题!相反,使用旧的 Kernel32.dll 函数,如 GetVersion
,例如:
bool IsWindowsVersionOrGreater(unsigned short version)
{
return _byteswap_ushort((unsigned short)GetVersion()) >= version;
}
// Usage: IsWindowsVersionOrGreater(_WIN32_WINNT_WINTHRESHOLD)