之所以要写这篇文字,是在做一个安装程序时发现要探测Windows版本信息格外复杂,比如想根据平台不同可选择不同的安装文件,运行在x86平台上的Windows 32bit OS只能安装32bit文件,而运行在x64平台上的Windows 64bit OS则可以选择安装32bit或64bit(x64),但是运行在x64平台上的Windows 32bit OS又只能安装32bit了,最后,运行在IA64平台上的Windows 64bit则可以选择安装32bit和64bit(IA64)。
首先,是一种常用的,在程序运行时判断操作系统是否为64bit的方法:调用kernel32.dll的IsWOW64Process函数。注意,由于该函数是Windows XP SP2(Client),Windows Server 2003(Server)以后才被加入,所以,必须是动态Load该函数。
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL IsWow64()
{
BOOL bIsWow64 = FALSE;
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
if (NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
{ // handle error }
}
return bIsWow64;
}
这种方法可以迅速的判断当前进程是否运行在WOW64中,如果是,则当前平台为Windows 64bit,否则为Windows 32平台。问题是,这种方法依旧没法判断64bit的OS到底是x64还是IA64。
其次,Windows API在Windows XP以及其后的系统还加入了一个函数:GetNativeSystemInfo。配合上GetVersionEx,可以得出Windows系统的详细版本。
typedef enum eWindowsPlatform
{
X86 = 0,
X64 = 1,
IA64 = 2
}
WindowsPlatform;
WindowsPlatform GetWindowsPlatform()
{
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
PGNSI pGNSI;
BOOL bOsVersionInfoEx;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return X86;
}
// Call GetNativeSystemInfo if supported
// or GetSystemInfo otherwise.
pGNSI = (PGNSI) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if(NULL != pGNSI)
pGNSI(&si);
else GetSystemInfo(&si);
switch (osvi.dwPlatformId)
{
// Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
{
if (si.wProcessorArchitecture ==
PROCESSOR_ARCHITECTURE_IA64 )
return IA64;
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
return X64;
else
return X86;
}
break;
// Test for the Windows Me/98/95.
default:
return X86;
}
}
我在这里忽略掉了具体的Windows的版本信息,如果想判断具体是什么系统,只需要得到判断一下得到的OSVERSIONINFOEX 的dwMajorVersion以及dwMinorVersion即可。
dwMajorVersion:
Value
Meaning
4
The operating system is Windows NT 4.0, Windows Me, Windows 98, or Windows 95.
5
The operating system is Windows Server 2003 R2, Windows Server 2003, Windows XP, or Windows 2000.
6
The operating system is Windows Vista or Windows Server 2008.
dwMinorVersion:
Value
Meaning
0
The operating system is Windows Vista, Windows Server 2008, Windows 2000, Windows NT 4.0, or Windows 95.
1
The operating system is Windows XP.
2
The operating system is Windows Server 2003 R2, Windows Server 2003, or Windows XP Professional x64 Edition.
10
The operating system is Windows 98.
90
The operating system is Windows Me.
由此,对制作一个因为操作系统版本、平台不同而安装不同模块的安装程序,已经足够了。
// testWindows.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
//#include
//#include
//using namespace std;
//
//typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
//LPFN_ISWOW64PROCESS fnIsWow64Process;
//
//BOOL IsWow64()
//{
// BOOL bIsWow64 = FALSE;
// fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
// if (NULL != fnIsWow64Process)
// {
// if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
// { // handle error }
// }
// return bIsWow64;
// }
//}
//int _tmain(int argc, _TCHAR* argv[])
//{
// bool ret = IsWow64();
// cout<
//}
#include
//#include "osInfor.h" //头文件,对下面几个函数的申明,略.
#include
#include
#include
#include
using namespace std;
#define BUFSIZE 100
//全局变量
BOOL g_bIsVista64 = FALSE;
BOOL g_bIsXP64 = FALSE;
//vista / NT
BOOL g_bVista = FALSE;
BOOL g_bNT32PlatForm = FALSE;
BOOL g_bIsWin2K = FALSE;
BOOL IsNT32Platform()
{
return g_bNT32PlatForm;
}
BOOL IsVista()
{
return g_bVista;
}
BOOL IsVista64()
{
return g_bIsVista64;
}
BOOL IsXp64()
{
return g_bIsXP64;
}
BOOL IsWin2K()
{
return g_bIsWin2K;
}
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
BOOL GetOsInfor(LPTSTR pszOS)
{
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
PGNSI pGNSI;
PGPI pGPI;
BOOL bOsVersionInfoEx;
DWORD dwType;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
//Get Version Information
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
return 1;
}
// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
pGNSI = (PGNSI) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if(NULL != pGNSI)
{
pGNSI(&si);
}
else
{
GetSystemInfo(&si);
}
//vista / xp /2k(2kÒÔÉÏOS)
if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId &&
osvi.dwMajorVersion > 4 )
{
g_bNT32PlatForm = TRUE;
StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
//Vista
if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 )
{
g_bVista = TRUE;
// Test for the specific product.
if( osvi.wProductType == VER_NT_WORKSTATION )
{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
}
else
{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
}
pGPI = (PGPI) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"GetProductInfo");
pGPI( 6, 0, 0, 0, &dwType);
switch( dwType )
{
case /*PRODUCT_ULTIMATE*/1:
StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
break;
case /*PRODUCT_HOME_PREMIUM*/2:
StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
break;
case /*PRODUCT_HOME_BASIC*/3:
StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
break;
case /*PRODUCT_ENTERPRISE*/4:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
break;
case /*PRODUCT_BUSINESS*/5:
StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
break;
case /*PRODUCT_STARTER*/6:
StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
break;
case /*PRODUCT_CLUSTER_SERVER*/7:
StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
break;
case /*PRODUCT_DATACENTER_SERVER*/8:
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
break;
case /*PRODUCT_DATACENTER_SERVER_CORE*/9:
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
break;
case /*PRODUCT_ENTERPRISE_SERVER*/10:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
break;
case /*PRODUCT_ENTERPRISE_SERVER_CORE*/11:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
break;
case /*PRODUCT_ENTERPRISE_SERVER_IA64*/12:
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
break;
case /*PRODUCT_SMALLBUSINESS_SERVER*/13:
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
break;
case /*PRODUCT_SMALLBUSINESS_SERVER_PREMIUM*/14:
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
break;
case /*PRODUCT_STANDARD_SERVER*/15:
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
break;
case /*PRODUCT_STANDARD_SERVER_CORE*/16:
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
break;
case /*PRODUCT_WEB_SERVER*/17:
StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
break;
default:
//printf("Product Type: %d/n", dwType);
break;
}
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
{
StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
g_bIsVista64 = TRUE;
}
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
{
StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
}
else
{
}
}//Vista
//server 2003
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
{
if( GetSystemMetrics(SM_SERVERR2) )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
}
else if ( osvi.wSuiteMask==VER_SUITE_STORAGE_SERVER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
}
else if( osvi.wProductType == VER_NT_WORKSTATION &&
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
g_bIsXP64 = TRUE;
}
else
{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));
}
// Test for the server type.
if ( osvi.wProductType != VER_NT_WORKSTATION )
{
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
}
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
}
}
else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
}
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
}
else
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
}
}
else
{
if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
}
else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
}
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
}
else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
}
else
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
}
}
}
}//server2003
//xp
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
}
//2k
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
{
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));
g_bIsWin2K = TRUE;
if ( osvi.wProductType == VER_NT_WORKSTATION )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
}
else
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
}
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
}
else
{
StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
}
}
}
// Include service pack (if any) and build number.
if( _tcslen(osvi.szCSDVersion) > 0 )
{
StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
}
TCHAR buf[80];
StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
StringCchCat(pszOS, BUFSIZE, buf);
return TRUE;
}
else//earlier windows
{
g_bNT32PlatForm = FALSE;
//printf( "This sample does not support this version of Windows./n");
return FALSE;
}
}
typedef enum eWindowsPlatform
{
X86 = 0,
X64 = 1,
IA64 = 2
}
WindowsPlatform;
WindowsPlatform GetWindowsPlatform()
{
OSVERSIONINFOEX osvi;
SYSTEM_INFO si;
PGNSI pGNSI;
BOOL bOsVersionInfoEx;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return X86;
}
// Call GetNativeSystemInfo if supported
// or GetSystemInfo otherwise.
pGNSI = (PGNSI) GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")),
"GetNativeSystemInfo");
if(NULL != pGNSI)
pGNSI(&si);
else GetSystemInfo(&si);
switch (osvi.dwPlatformId)
{
// Test for the Windows NT product family.
case VER_PLATFORM_WIN32_NT:
{
if (si.wProcessorArchitecture ==
PROCESSOR_ARCHITECTURE_IA64 )
return IA64;
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
return X64;
else
return X86;
}
break;
// Test for the Windows Me/98/95.
default:
return X86;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
WindowsPlatform retWindows = GetWindowsPlatform();
cout<
}