C ++如何检测Windows 10

问题描述 投票:21回答:4

我多年前编写了一个PC审计工具,并一直保持最新状态。其中一个基本功能是报告正在审核的PC上运行的Windows版本,我一直使用GetVersionEx调用。

这适用于Windows 8,但在Windows 10下不受支持,Windows 10确实像Windows 8一样返回8.2。 Microsoft似乎没有引入任何直接替代品,而是建议您检查所需的特定功能而不是查看操作系统,但出于审计的目的,我实际上需要操作系统名称。

'scanner'是一个C ++程序,必须在非特权帐户下运行,所以我不认为我读过另一个建议 - 拿起系统DLL的版本如kernel32.dll将起作用,因为这些文件夹通常无法访问给用户。

欢迎任何其他建议/想法!

c++ windows windows-10
4个回答
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等


12
投票

从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函数,因此行为VerifyVersionInfoIsWindows8Point1OrGreater同样受到清单的存在和内容的影响。

要显示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>\\ProductVersionRtlGetVersion()NetServerGetInfo()代替。他们都报告了一个准确的操作系统版本,并且不受表现(但是?)。


1
投票

我需要这个在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运行附加清单的最后一位。我找到的例子没有运气,现在只是“欺骗”了这批...


1
投票

使用以下功能:

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)。

© www.soinside.com 2019 - 2024. All rights reserved.