怎样利用GetVersion函数来判断当前操作系统

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)怎的利用GetVersion函数来判断当前操作系统是Win95/98、Win2000/XP、Vista/Win7呢(2) - VB当前位置:& &&&怎的利用GetVersion函数来判断当前操作系统是Win95/怎的利用GetVersion函数来判断当前操作系统是Win95/98、Win2000/XP、Vista/Win7呢(2)www.MyException.Cn&&网友分享于:&&浏览:15次
&&&dwMinorVersion&As&Long
&&&dwBuildNumber&As&Long
&&&dwPlatformID&As&Long
&&&szCSDVersion&As&String&*&128
Public&OsName$,&TmpStr$,&Ary
Private&Sub&Form_Activate()
&&&Ary&=&Array("",&"Windows&95",&"Windows&98",&"Windows&Me",&"Windows&NT4.0",&"Windows&2000",&"Windows&XP",&"Windows&2003",&"Windows&Vista",&"Windows&7")
&&&MsgBox&"您的操作系统是:"&&&Ary(GetVersion)
Public&Function&GetVersion()&As&Long
&&&Dim&OSInfo&As&OSVERSIONINFO
&&&Call&GetVersionEx(OSInfo)
&&&OSInfo.dwOSVersionInfoSize&=&148
&&&OSInfo.szCSDVersion&=&Space(128)
&&&Call&GetVersionEx(OSInfo)
&&&Select&Case&OSInfo.dwPlatformID
&&&&&&Case&VER_PLATFORM_WIN32s
&&&&&&&&&OsName&=&"Windows&3.1"
&&&&&&Case&VER_PLATFORM_WIN32_WINDOWS
&&&&&&&&&OsName&=&"Windows&98"
&&&&&&Case&VER_PLATFORM_WIN32_NT
&&&&&&&&&OsName&=&"Windows&NT"
&&&End&Select
&&&TmpStr&=&OsName&&&"("&&&OSInfo.dwMajorVersion&&&"."&&&OSInfo.dwMinorVersion&&&")"
&&&If&InStr(TmpStr$,&"95")&Then&GetVersion&=&1:&Exit&Function
&&&If&InStr(TmpStr$,&"98")&Then&GetVersion&=&2:&Exit&Function
&&&If&InStr(TmpStr$,&"Me")&Then&GetVersion&=&3:&Exit&Function
&&&If&InStr(TmpStr$,&"4.0")&Then&GetVersion&=&4:&Exit&Function
&&&If&InStr(TmpStr$,&"5.0")&Then&GetVersion&=&5:&Exit&Function
&&&If&InStr(TmpStr$,&"5.1")&Then&GetVersion&=&6:&Exit&Function
&&&If&InStr(TmpStr$,&"5.2")&Then&GetVersion&=&7:&Exit&Function
&&&If&InStr(TmpStr$,&"6.0")&Then&GetVersion&=&8:&Exit&Function
&&&If&InStr(TmpStr$,&"6.1")&Then&GetVersion&=&9
End&Function------解决方案--------------------获取Windows操作系统所有版本
http://www.mndsoft.com/blog/VB6/0964.html 共&2&页:
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有获取操作系统版本的几种方法
获取操作系统版本的几种方法
相关的例子:
作者:谢平&nbsp于上传&
&&&&&& Win32 APIGetVersionExMSDNE
&&&&&& GetVersionEx
BOOL GetVersionEx(LPOSVERSIONINFO &lpVersionInformation);
&& OSVERSIONINFOBOOLGetLastErrorVisual stdioERROR &LOOK.EXE
&&&&&& OSVERSIONINFOdwOSVersionInfoSizeOSVERSIONINFOOSVERSIONINFOEX
&&&& 哈哈,忘了说这个结构的具体内容了。
typedef struct
_OSVERSIONINFO{
dwOSVersionInfoS &&& //设置为OSVERSIONINFO结构的大小
dwMajorV & &&&&&&&& //操作系统的主版本号
dwMinorV & &&&&&&&& //操作系统的副版本号
dwBuildN &
&&&&&&&& //操作系统Build(构建)编号
dwPlatformId;
&&&&&&&&&&&&&&&&&& //操作系统的平台
szCSDVersion[128];
&&&&&&&& //服务补丁号
OSVERSIONINFO;
在这里我们只使用OSVERSIONINFO结构,因为GetVersionEx使用的是OSVERSIONINFO结构类型的指针,如果使用OSVERSIONINFOEX的话,会涉及到结构指针类型的转换问题,对于这个问题我没有很好的解决方案,如果你有的话请发扬一下共享精神,告诉我一下哈哈。
&& 下面的这个表节选自http://www.codeproject.com/,我对这个表格添加了一些内容。通过这个表可以很清楚的查到大部分操作系统对应字段的值。
&&&&&&&&&&&&&&&&&&&&&&&&&&& .data
&&&&&&&& OSVERSIONINFO &?&
&&&&&&&&&&&&&&&&&&&&&&&&&&& .code
;dwOSVersionInfoSize为OSVERSIONINFO结构的大小
&&& osVersion.dwOSVersionInfoSize, SIZEOF OSVERSIONINFO
invoke & GetVersionEx,
addr osVersion
&&& eax == 0
&&&&&&&&&&&
&&& &&&&& invoke
GetLastError&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;
&&&&& & .if & osVersion.dwMajorVersion == 4
&&&&&&&&&&&&&&&&&&& &&&&&& ;NT4.0
&&&&& & .elseif
osVersion.dwMajorVersion == 5
&&&&&&&& .if
&&& osVersion.dwMinorVersion == 0
&&&&&&&&&&&&& &&&&&& ;Win 2000
&&&&&&&& .elseif osVersion.dwMinorVersion
&&&&&&&&&& ;XP
&&&&&&&& .elseif osVersion.dwMinorVersion
&&&&&&&&&& ;Win 2003
&&&&&&&& .endif
&&&&& .elseif osVersion.dwMajorVersion == 6 &&\
osVersion.dwMinorVersion==0&&&&&& ;Windows Vista
&&&&& & .endif&&&&&&& &&&
os OSVERSIONINFOos.asmos.rcos.exe
&&&&&& HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\CSDVersionCurrentBuildNumberCurrentVersion”regedt32””regedit”
&&&&&& RegOpenKeyEx HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\RegQueryValueExRegCloseKey
Windows.inc
HKEY_CLASSES_ROOT
&&&&&&&&&&&&&&&&&&& & equ h
HKEY_CURRENT_USER
&&&&&&&&&&&&&&&&&&& equ
HKEY_LOCAL_MACHINE
&&&&&&&&&&&&&&&&& & equ h
HKEY_USERS
&&&&&&&&&&&&&&&&&&&&&&&&&& &&&& equ h
HKEY_PERFORMANCE_DATA
&&&&&&&&&&&&&& equ
HKEY_CURRENT_CONFIG
&&&&&&&&&&&&&&&&& equ
HKEY_DYN_DATA
&&&&&&&&&&&&&&&&&&&&&&& && equ h
RegOpenKeyExWin16RegOpenKeyWin32APIRegOpenKeyEx
&&&&&& invoke
&&& RegOpenKeyEx,hKey,lpSubKey,dwOptions,samDesired,phkResult
hKeylpSubKey\1\2\n\0
1HKEY_LOCAL_MACHINESoftware\RegTest\MySubkey
2HKEY_LOCAL_MACHINE\SoftwareRegTest\MySubkey
RegOpenKeyExhKeyHKEY_LOCAL_MACHINElpSubKeySoftware\RegTest\MySubkeyhKeyHKEY_LOCAL_ MACHINE\SoftwarelpSubKeyRegTest\MySubkeyhKeyHKEY_LOCAL_ MACHINEHKEY_LOCAL_MACHINE\Software
●&& dwOptions0
●&& samDesired
■&& KEY_ALL_ACCESS
■&& KEY_CREATE_LINK
■&& KEY_CREATE_SUB_KEY
■&& KEY_ENUMERATE_SUB_KEYS
■&& KEY_EXECUTE
■&& KEY_QUERY_VALUE
■&& KEY_READKEY_QUERY_VALUEKEY_ENUMERATE_SUB_KEYSKEY_ NOTIFY
■&& KEY_SET_VALUE
■&& KEY_WRITEKEY_SET_VALUEKEY_CREATE_SUB_KEY
●&& phkResult
ERROR_SUCCESSphkResult
RegCloseKey
&&&&&& invoke
&&& RegCloseKey,hKey
ERROR_SUCCESS
RegQueryValueEx
&&&&&& invoke
&&& RegQueryValueEx,hKey,lpValueName,lpReserved,\
&&&&&&&&&&&&&&&&&&&& lpType,lpData,lpcbData
hKeylpValueName lpReserved0lpData
RegSetValueEx
●&& lpTypeNULL
●&& lpcbDatalpcbData
ERROR_SUCCESSERROR_MORE_DATAlpcbData
lpDataNULLlpcbDataNULLlpcbDatalpcbDatalpDataNULLERROR_SUCCESS
KEY_QUERY_VALUE
&&&&&& os Reg
&&&&&& ZwQueryKey ZwQueryKeyZwCloseKmdkitKdmkit\examples\basic\RegistryWorks
&&&&&& PsGetVersion
BOOLEAN& PsGetVersion
&&&&&& PULONG
&&&& MajorVersion
&&&&&& OPTIONNAL
&&&&&& PULONG
&&&& MinorVersion OPTIONNAL
&&&&&& PULONG
&&&& BuildNumber OPTIONNAL
&&&&&& PUNICODE_STRING&&&&& CSDVersion& OPTIONNAL
&&&&&& Win XPWin 2003RtlGetVersion APIOSVERSIONINFO
NTSTATUS& RtlGetVersion PRTL_OSVERSIONINFOW
& lpVersionInfomation );
PsGetVersion
&&&&&&&&&&&&&&&&&&&& &&&&&& .data
dwMajorVersion
dwMinVersion
&&&&& dd&& 0
dwBuildNumber
&&&&&&&&&&&&&&& &&&&&& dw& 256 dup(0)
usCSDVersion
&&&&& UNICODE_STRING {sizeof
usz-2, sizeof usz,offset usz}
&&&&&&&&&&&&&&&&&&&& .code
&&& PsGetVersion,addr dwMajorVersion,addr dwMinVersion,\
addr dwBuildNumber,addr
usCSDVersion
&&& dwMajorVersion == 4
&&&&&&&&&&&&&& ;NT4.0
&&&&& dwMajorVersion == 5
&&&&&& .if
&&& dwMinVersion == 0
&&&&&&&&&&& &&&&&& ;Win 2000
&&&&&& .elseif
&&&&& dwMinVersion == 1
&&&&&&&&&&& ;Win XP
&&&&&& .elseif
&&&&& dwMinVersion == 2
&&&&&&&&&&& ;Win 2003
&&&&&& .endif
&&&&& dwMajorVersion == 6 && dwMinVersion == 0 && ;Vista
usCSDVersion& UNICODE_STRING
欢迎访问AoGo汇编小站:Windows API 中有两个函数可以得到系统版本信息:GetVersion和GetVersionEx。
&&&&& GetVersion这个函数曾经困扰了很多程序员,其本来设计的是在DWORD返回值中用低位的那个字表示MS-DOS的版本号,高位的那个字表示Windows版本号。对于每个字来说,高位字节代表主要版本号,低位字节代表次要版本号。可是因为编写此函数的程序员犯了一个错误,使得此函数返回的Windows版本号颠倒了(即把主要版本号放到了低位字节,而次要版本号放到了高位字节)。当发现此错误的时候已经有很多程序员在使用这个函数了,Microsoft只好将错就错,直接把原来的API文档给改了过来。
&&&&& 为了解决GetVersion带来的问题,Microsoft后来开发了一个新的函数GetVersionEx,用它能够得到更详细的Windows系统的版本信息,下面我就写写GetVersionEx的使用方法。
函数原型:
BOOL GetVersionEx(POSVERSIONINFO pVersionInformation);
我们先来看看OSVERSIONINFOEX这个结构:
typedef struct {
DWORD dwOSVersionInfoS&&&&&& //在使用GetVersionEx之前要将此初始化为结构的大小
DWORD dwMajorV&&&&&&&&&&&&&& //系统主版本号
DWORD dwMinorV&&&&&&&&&&&&&& //系统次版本号
DWORD dwBuildN&&&&&&&&&&&&&& //系统构建号
DWORD dwPlatformId;&&&&&&&&&&&&&&&&& //系统支持的平台(详见附1)
TCHAR szCSDVersion[128];&&&&&&&&& //系统补丁包的名称
WORD wServicePackM&&&&&&&&&&& //系统补丁包的主版本
WORD wServicePackM&&&&&&&&&&& //系统补丁包的次版本
WORD wSuiteM&&&&&&&&&&&&&&&&&&&&& //标识系统上的程序组(详见附2)
BYTE wProductT&&&&&&&&&&&&&&&&&&& //标识系统类型(详见附3)
BYTE wR&&&&&&&&&&&&&&&&&&&&&&&& //保留,未使用
} OSVERSIONINFOEX, *POSVERSIONINFOEX;
这个结构在Windows 2000后出现,老版本的OSVERSIONINFO结构没有wServicePackMajor、wServicePackMinor、wSuiteMask、wProductType和wReserved这几个成员。
接着在调用函数之前先初始化结构的大小:
OSVERSIONINFOEX
os.dwOSVersionInfoSize=sizeof(os);
函数返回值为TRUE表示成功:
if(!GetVersionEx((OSVERSIONINFO *)&os))
&&&&& return FALSE;
函数调用成功以后就可以通过OSVERSIONINFOEX来查看系统的版本信息了。
getSystemName()
&&&&SYSTEM_INFO
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&GetSystemInfo(&info);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&OSVERSIONINFOEX
&&&&os.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX);&
&&&&if(GetVersionEx((OSVERSIONINFO
*)&os))&&&&&&&&&&&&&&&&&
&&&&&&&&CString
&&&&&&&&switch(os.dwMajorVersion){&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&switch(os.dwMinorVersion){&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&if(os.dwPlatformId==VER_PLATFORM_WIN32_NT)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows NT 4.0&);&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&else
if(os.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows 95&);
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows 98&);
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Me&);
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&switch(os.dwMinorVersion){&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows 2000&);&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows XP&);&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&if(os.wProductType==VER_NT_WORKSTATION
&&&&&&&&&&&&&&&&&&&&&&&&&&&info.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows XP Professional x64 Edition&);
&&&&&&&&&&&&&&&&&&&&&&&&else
if(GetSystemMetrics(SM_SERVERR2)==0)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Server 2003&);&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&else
if(GetSystemMetrics(SM_SERVERR2)!=0)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Server 2003 R2&);
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&switch(os.dwMinorVersion){
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&if(os.wProductType==VER_NT_WORKSTATION)
&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Vista&);
&&&&&&&&&&&&&&&&&&&&&&&&else
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Server 2008&);&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&&&&&case
&&&&&&&&&&&&&&&&&&&&&&&&if(os.wProductType==VER_NT_WORKSTATION)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows 7&);
&&&&&&&&&&&&&&&&&&&&&&&&else
&&&&&&&&&&&&&&&&&&&&&&&&&&&&vname=_T(&Microsoft
Windows Server 2008 R2&);
&&&&&&&&&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&break;
&&&&&&&&&&&&default:
&&&&&&&&&&&&&&&&vname=_T(&未知操作系统&);
&&&&&&&&return
&&&&&&&&return去调试微软对这个API做了什么改动意义不大,反正现在的结果就是这个API返回的值不对了,API也开始说谎了~不过在[1]里面,微软同时给出一个解决方案,嗯,一边跟你说,这个API已经被废弃了,一边又说还是可以用的,这不是坑爹是什么……解决方案是什么呢?修改manifest文件。加一段compatibility节点。&?xml version="1.0"encoding="UTF-8" standalone="yes"?&&assembly manifestVersion="1.0"xmlns="urn:schemas-microsoft-com:asm.v1"xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"&
&description& my appexe &/description&
&trustInfoxmlns="urn:schemas-microsoft-com:asm.v3"&
&security&
&requestedPrivileges&
&requestedExecutionLevel
level="asInvoker"
uiAccess="false"
&/requestedPrivileges&
&/security&
&/trustInfo&
&compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"&
&application&
&!-- Windows 8.1 --&
&supportedOSId="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/&
&!-- Windows Vista --&
&supportedOSId="{e6-43c5-a5fe-008deee3d3f0}"/&
&!-- Windows 7 --&
&supportedOSId="{d96-4fbd-8e2d-aa}"/&
&!-- Windows 8 --&
&supportedOSId="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/&
&/application&
&/compatibility&&/assembly&主要就是compatibility部分了,如果你已经有manifest文件了,只需要添加compatibility部分即可。对了Windows10怎么办?貌似[1]里面还没有说啊,别急,用&!-- Windows 10 --&&supportedOSId="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/&就好了,怎么知道的?请叫我雷锋!在Windows10下面测试一把的结果如图。 兼容模式的影响还有一个可能的情况会造成GetVersionExW返回的系统版本和实际的系统版本不一样。这个与Windows8.1,Windows10没有什么关系。纯粹是为了兼容考虑,在设置兼容模式之后,GetVersionExW返回的是兼容的目标版本的系统版本。启动调试去查看应用程序的PEB是不是被修改过了,结果发现,并没有修改过PEB。那么问题来了,为什么GetVersionExW的值发生变化了呢?直接调试GetVersionExW发现,在设置兼容模式之后,微软使用IATHook的方式,Hook了一堆的(嗯,不是1-2个,而是一堆)系统API,其中GetVersionExW就被AcLayers.dll里面的一个函数给Hook了,然后Hook函数里面返回了兼容系统版本号。 怎样判断兼容模式一般来说,应用程序不需要判断当前是否处于兼容模式下运行,微软实现这个机制的目的本意就是想对应用程序透明。主要是很多“古老的”程序内部严格限定只能在某个具体的系统下运行,譬如限定在WindowsXP SP3下运行(因为当时微软的系统最高版本可能就是XP),这样当用户操作系统升级之后,譬如升级到了Windows7,这个时候问题来了!本来一般情况下微软的系统是可以前向兼容的,结果应用程序自己主动不兼容,发现不是XP,主动退出,导致用户用不了了,因此微软发明了一个兼容模式,高版本的系统可以模拟一个低版本的系统运行环境,这样就解决大量的类似问题。在兼容模式下,当应用程序调用GetVersionExW等API时,返回的是兼容的目标系统的系统版本,当然这只是兼容模式技术解决的一个问题而已,但是是较重要的一个问题(兼容模式还解决了很多其它问题)。一般的应用程序不需要关心这个兼容模式。但是某些特殊的应用程序却恰恰需要,应用程序可能会根据不同的系统版本做不同的事情,而一个可能性是用户误把应用程序设置为某个低版本操作系统兼容运行,导致整个程序运行反而异常。举个例子,像系统补丁修复程序,一般来说漏洞补丁都是和系统版本一一对应,如果程序使用GetVersionExW来获取系统版本,那么程序运行在Windows7下面,因为兼容模式的影响,导致补丁修复程序推送了一大批WindowsXP下面的补丁,想想这个场景,也是有点尴尬的。从大部分的使用场景上面来说,放弃使用GetVersionExW也许是一个更好的选择。通过其它方式拿到更精确的系统版本,不用考虑兼容模式的副作用,也不用担心Windows8(主要是指Window8.1和Window10)以上的系统获取到错误的系统版本。那么怎么判断当成程序正在兼容模式运行呢?方法应该有很多,比较简单的方法,[4]里面介绍过一种,不过这种方法要注意,在Windows8.1之后,它可能给出错误的结果,要按照上面提到的办法,让GetVersionExW返回正确的值。另外一种更好的方法是判断注册表里面的应用程序兼容模式记录列表,当把一个应用程序设置为兼容模式或者管理员权限启动之后,系统会在HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers下面记录相应的信息,如果想所有用户起效,则修改HKEY_LOCAL_MACHINE\\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers即可。我们可以试试设置之后的效果。我在Windows7SP1下面随意设置了几个。可以很清楚的看到两个程序被设置为兼容WIN7RTM运行和兼容WINXPSP3运行,如果你去掉这两个注册表值,则应用程序就不再以兼容模式运行,因此实际上可以检测这个位置判断哪些程序被设置为兼容模式运行,甚至可以通过删除这里的内容,去掉某些应用程序的兼容模式设置。同时可以发现的是微软用很容易识别的字符串来描述兼容的目标系统,更多的兼容描述字符串可以参考[3],另外要注意的是从Windows8开始,这些字符串前面多了一个波浪线和空格(~ ),譬如兼容WINXPSP3,在Windows10下面是~ WINXPSP3。 判断系统版本更好的办法GetVersionExW既然被微软废弃了,再使用总觉得拔凉拔凉的,有什么更好的判断系统版本的方法吗?答案是肯定的!下面给出几种实践中用过的方法。1、首先从原理上来说,GetVersionExW是读取的PEB里面的版本信息,其实我们自己也可以读取PEB嘛,只是麻烦一点。这个就不给例子了。有兴趣可以自己实现一下。2、微软在[1]里面其实推荐过一批更好的API([7]),号称接口名更人性化,从名字上面看确实含义更清晰了,不过使用起来是否方便就仁者见仁智者见智了,随意罗列几个,不过这套API声明在&VersionHelpers.h&里面,比较新的SDK才有。VERSIONHELPERAPI IsWindows7OrGreater()VERSIONHELPERAPIIsWindows7SP1OrGreater()VERSIONHELPERAPI IsWindows8OrGreater()VERSIONHELPERAPI IsWindows8_1OrGreater()VERSIONHELPERAPI IsWindowsServer() 3、使用VerifyVersionInfo来进行版本判断(参考[8]),这个API声明在winbase.h里面,从Windows2000系统就已经开始提供了,但是我们可能很少使用,说实话,使用起来不是特别方便。我们先看看是怎么使用的,它本质是进行版本比较。BOOL WINAPI VerifyVersionInfo( _In_
LPOSVERSIONINFOEX lpVersionInfo, _In_
DWORD dwTypeMask, _In_
DWORDLONG dwlConditionMask);这个函数的原型里面第一个参数是熟悉的OSVERSIONINFOEX,但是这里是做为传入参数使用,第二个参数dwTypeMask用于指定要比较哪些项,可以比较主版本,次版本,Build号等等,可以使用位组合。第三个参数则是比较的方法,是&、=还是&,或者&=,&=等等,可以通过VER_SET_CONDITION来设置,可以进行各种组合来判断,还是比较灵活的。看两个例子吧。BOOL IsWinVerGreaterThan(DWORDdwMajorVersion, DWORD dwMinorVersion){
OSVERSIONINFOEXW osvi = {0};
DWORDLONG dwlConditionMask = 0;
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize= sizeof(osvi);
osvi.dwMajorVersion= dwMajorVersion;
osvi.dwMinorVersion= dwMinorVersion;
// 主版本号判断
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER);
if (::VerifyVersionInfoW(&osvi, VER_MAJORVERSION, dwlConditionMask))
return TRUE;
// 次版本号判断
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER);
return ::VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask);} //-------------------------------------------------------------------------// 函数
: IsWinVerEqualTo// 功能
: 判断是否=某个特定的系统版本// 返回值
: BOOL // 参数
: DWORD dwMajorVersion// 参数
: DWORD dwMinorVersion// 附注
: //-------------------------------------------------------------------------BOOL IsWinVerEqualTo(DWORDdwMajorVersion, DWORD dwMinorVersion){
OSVERSIONINFOEXW osvi = {0};
DWORDLONG dwlConditionMask = 0;
// 1、初始化系统版本信息数据结构
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize= sizeof(osvi);
osvi.dwMajorVersion= dwMajorVersion;
osvi.dwMinorVersion= dwMinorVersion;
// 2、初始化条件掩码
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_EQUAL);
return ::VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask);}封装一下使用就更方便了,譬如要判断当前是Window7,用IsWinVerEqualTo(6,1)即可。或者你不想暴露一些“恶心”的MagicNumber,可以再封装一个IsWindows7()嘛。 4、还有一个我个人比较喜欢的方法是使用一个未文档化的函数来获取系统版本,也就是RtlGetNtVersionNumbers,这个是NTDLL里面的一个未文档化函数。但是这个函数微软把它导出了,因此我们就有办法使用了。使用方法://-------------------------------------------------------------------------// 函数
: GetNtVersionNumbers// 功能
: 调用RtlGetNtVersionNumbers获取系统版本信息// 返回值
: BOOL // 参数
: DWORD& dwMajorVer 主版本// 参数
: DWORD& dwMinorVer 次版本// 参数
: DWORD& dwBuildNumber build号// 附注
: //-------------------------------------------------------------------------BOOL GetNtVersionNumbers(DWORD&dwMajorVer, DWORD& dwMinorVer,DWORD& dwBuildNumber){
BOOL bRet= FALSE;
HMODULE hModNtdll= NULL;
if (hModNtdll= ::LoadLibraryW(L"ntdll.dll"))
typedef void (WINAPI *pfRTLGETNTVERSIONNUMBERS)(DWORD*,DWORD*, DWORD*);
pfRTLGETNTVERSIONNUMBERS pfRtlGetNtVersionNumbers;
pfRtlGetNtVersionNumbers = (pfRTLGETNTVERSIONNUMBERS)::GetProcAddress(hModNtdll, "RtlGetNtVersionNumbers");
if (pfRtlGetNtVersionNumbers)
pfRtlGetNtVersionNumbers(&dwMajorVer, &dwMinorVer,&dwBuildNumber);
dwBuildNumber&= 0x0
bRet = TRUE;
::FreeLibrary(hModNtdll);
hModNtdll = NULL;
return bRet;}使用未文档化的函数要注意的一个点是,需要分析清楚函数的传入参数的类型,否则传错了类型,如果类型大小不一样,轻则函数出错,重则程序崩溃(尤其是传出参数)。我们可以看下RtlGetNtVersionNumbers这个函数是怎么实现的(调试用的ntdll.dll的版本是6.1.,其它系统的也差不多的,仅仅是Hardcode的数字不一样),下面是它的实现伪码(IDA生成)。int __stdcall RtlGetNtVersionNumbers(int a1, int a2, int a3){ int // eax@5
*(_DWORD *)a1 = 6; if ( a2 )
*(_DWORD *)a2 = 1; result = a3; if ( a3 )
*(_DWORD *)a3 = 0xF0001DB1u; }我只能说微软,你干得漂亮!直接Hardcode处理,简单干净! 5、还有一种方法是直接去获取NTDLL这个系统关键文件(其它的文件也可行,但是实践证明NTDLL最好)的文件版本号,一般来说,该文件的版本基本上就是系统的版本。像[4]里面用到的判断兼容的方法就是通过对比GetVersionEx的返回值和关键系统文件的版本,来判断是否当前应用程序处理兼容模式下 注:建议不要使用RtlGetVersion来进行版本判断。Windows2003之前它的行为在兼容模式下和GetVersionExW不一致,Vista之后在兼容模式下它的行为和GetVersionExW一致。 效果展示分别在WindowsXP,Windows7,Windows10下面测试了这些方法。注意左边的是常规模式运行,右边的是兼容模式运行。 参考文献[1] Operating system version changes inWindows 8.1 and Windows Server 2012 R2 http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074(v=vs.85).aspx[2] GetVersionExhttp://msdn.microsoft.com/en-us/library/ms724451(VS.85).aspx[3] Running an Application asAdministrator or in Compatibility Mode http://www.verboon.info/2011/03/running-an-application-as-administrator-or-in-compatibility-mode/[4] http://blog.csdn.net/magictong/article/details/5829065[5] http://blogs.msdn.com/b/chuckw/archive//manifest-madness.aspxMadness[6] OSVERSIONINFOEX structure http://msdn.microsoft.com/en-us/library/ms724833(v=vs.85).aspx[7] Version Helper functions http://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx[8] VerifyVersionInfofunction http://msdn.microsoft.com/en-us/ms725492(VS.85).aspx
本文已收录于以下专栏:
他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 利用函数图像判断方程 的文章

 

随机推荐