1.2 Определение версии Windows
Windowsпостоянно совершенствуется, выпускаются новые версии системы, а в них предусматриваются новые интересные возможности. Так что при разработке приложений нередко приходится решать сложную дилемму. С одной стороны, хочется украсить свое приложение достижениями, которые предоставляют новые версииWindows. Ас другой стороны, от приложения требуется универсальность: вы не знаете, какая версия системы будет поставлена на компьютере будущего пользователя вашего приложения. И надо, чтобы на любых возможных версиях ваше приложение нормально работало.
Для успешного решения подобной проблемы надо, чтобы приложение во время выполнения умело определять версию Windows. Тогда в зависимости от версии оно сможет наиболее эффективно использовать те или иные возможности системы.
Имеются две функции, позволяющие получить информацию о версии Windows:GetVersionиGetVersionEx. Первая из них объявлена в файлеwinbase.hследующим образом:
DWORD GetVersion (VOID);
Эта функция сейчас считается устаревшей, и в новых приложениях рекомендуется применять GetVersionEx. Но я, все-таки, рассмотрю коротко и функциюGetVersion, так как есть случаи, когда она удобнее. Функция возвращает значение, содержащее в младшем слове нрмер версииWindows, а в старшем — информацию о платформе операционной системы.
Младший байт младшего слова содержит основной номер Windowsв шестнадцатеричном виде, а его старший байт (в версиях,Windows95) содержит дополнительный номер (модификацию) тоже в шестнадцатеричном виде. Таким образом, при распознавании версий можно руководствоваться следующей таблицей:
|
Платформа |
Старший бит |
Младший бит (основной номер версии) |
|
Windows NT |
0 |
3или 4 |
|
Windows 95 |
1 |
4 |
|
Win32 c Windows 3.1 |
1 |
3 |
Следующий пример демонстрирует дешифрацию этой информации (он содержится в каталоге Windowsв проектеPWinVerна приложенном к кнмге диске):
#include "windef.h"
String GetWindowsVersion()
{
Word dwBuild;
String S;
DWord dwVersion = GetVersion() ;
Word dwMajor Version = (Byte)((Word)dwVersion);
Word dwMinorVersion = HIBYTE({Word)dwVersion);
if (dwVersion-< 0X80000000}
{
switch (dwMajo.rVersion)
{
case 4: S = "Windows NT";
break;
case 5: if (dwMinorVersion == 0)
S = "Windows_2000";
else if (dwMinorVersion == 1)
S = "Windows XP";
else S = "Неизвестная версия Windows NT";
break;
default: S = "Неизвестная версия Windows NT";
}
dwBuild = HIWORD(dwVersion) ;
}
else if (dwMajorVersion < 4)
{
S = "Windows 3.1";
dwBuild = HIWORD(dwVersion) & 0X7FFFFFFF;
}
else
{
if (dwMajorVersion ==4)
switch (dwMinorVersion)
{
case 0: S = "Windows 95";
break;
case 10: S = "Windows 98";
break;
case 90: S = "Windows ME";
break;
default:' S = "Неизвестная версия Windows 9x";
}
dwBuild = 0;
}
if (dwBuild > 0)
S = S + ", модификация " + IntTоStr. (dwBuild) ;
return S;
}
void __fastcall TFormI::ButtonlClick(TObject *Sender)
{
Memol->Text = GetWindowsVersion () ;
}
Функция GetVersionудобна, если не требуется информация о версиях, а надо только определить, относится лиWindowsк группеNT, или к группе 9х. Для этого достаточно выполнить оператор:
if (GetVersion() < 0х80000000)
{...}
Такую проверку удобно оформить в виде функции и включить в свою библиотеку:
bool IsNT ()
{
return (GetVersion() < 0х80000000)
}
В приложении PWinVerвызов этой функции оформлен следующим образом:
if (IsNT)
Memo1->Text = “Windows NT\\2000\\ME\\XP”;
else Memo1->Text = “Windows 9x”;
Если требуется более подробная информация о Windows, то, как уже было сказано, намного удобнее работать с более современной функциейGetVersionEx:
BOOL GetVersionEx (_OSVERSIONINFO *lpVersionInfo);
Ее единственный параметр указывает структуру типа _OSVERSIONINFO. Поля этой структуры содержат следующую информацию:
|
Поле |
Описание |
|
DWORD dwOSVersionInfoSize |
Размер структуры. Должен задаваться до вызова GetVersionEx |
|
DWORD dwMajorVersion |
Основной номер версии |
|
DWORD dwMinorVersion |
Дополнительный номер версии |
|
DWORD dwBuildNumber |
Для WindоwsNT– номер модификации. ДляWindоws9.х младшее слово – номер модификации, старший байт старшего слова – основной номер версии(то же, чтоdwMajorVersion), младший байт срашего слова – дополнительный номер версии(то же, чтоdwMinorVersion). |
|
DWORD dwPlatformId |
Платформа операционной системы: VER_PLATFORM_WIN32s – Windows 3.1 c Win32s VER_PLATFORM_WIN32_WINDOWS – Windows 9.x c Win32 VER_PLATFORM_WIN32_NT – Windows NT(2000/XP) c Win32 |
|
CHAR szCSDVersion[ 128 ] |
Необязательная дополнительная информация |
При использовании функции GetVersionExпример дешифрации информации оWindows, аналогичный приведенному ранее, может выглядеть так (см. проектPWinVerв каталогеWindiwsна приложенном к книге диске):
TOSVersionInfo OSVer;
AnsiString S;
ZeroMemory(&OSVer, sizeof(OSVer));
OSVer.dwOSVersionInfoSize = sizeof(TOSVersionInfo), if ( ! GetVersionEx(SOSVer))
return GetWindowsVersion() ;
switch (OSVer.dwPlatformId) {
case VER_PLATFORM_WIN32s: S = "Windows 3.1";
break;
case VER_PLATFORM_WIN32_WINDOWS;
if(OSVer.dwMajorVersion == 4)
swit'ch (OSVer.dwMinorVersion) { • case 0: S = "Windows 95";
,break;
case 10: if(OSVer.szCSDVersion[l] == 'A') S = "Windows 98SE";
else S = "Windows 98";
break;
case 90: S = "Windows ME";
break;
default: S = "Hen3Bec.THaa BepcMH Windows 9x";
} break;
case VER_PLATFORM_WIN32_NT:
switch (OSVer.dwMajorVersion)
{ ' .' • case 4: S = "Windows NT";
case 5; if(OSVer.dwMinorVersion == 0) • S = "Windows 2000";
else if (OSVer.dwMinorVersion ==1) S = "Windows XP";
else S =•"HeMSBecTHaa Bepcua Windows NT";
default: S = ^'HeMSBecTHaa Bepcna Windows NT";
}
). return S + "\r\nMOfln$nKamifl " + (String)OSVer.szCSDVersion + ' ' + IntToStr(OSVer.dwBuildNumber) ;
'}
void fastcall TFormI::Button2Click(TObject *Sender) { ' • • ' Memol->Text = GetWindowsVersion() ;
}
Просмотрев этот код, вы увидите, что означают и как надо анализировать поля записи TOSVersionInfo. Обратите внимание, что в приведенном коде функцииGetWindowsVersionExпроверяется значение, возвращаемое библиотечной функциейGetVersionEx, и если вызовGetVersionExзакончился неудачей, то вызывается рассмотренная ранее функцияGetWindowsVersionEx. Дело в том, что нередко с функциейGetVersionExмогут быть проблемы. Так что уж лучше подстраховаться.
Еще большие возможности дает вызов функции GetVersionExс использованием записи типаTOSVersionInfoЕх. Ниже приводится соответствующий код из того же приложенияString GetWindowsVersionExEx(String SSdop) {
struct TOsVersionInfoEx {
TOSVersionInfo old;
WORD wServicePackMajor;
WORD wServicePackMinor;
WORD wSuiteMa-sk;
BYTE wProductType;
BYTE wReserved;
} Verlnfo;
ZeroMemory(SVerInfo, sizeof(Verlnfo));
Verlnfo.old.dwOSVersionInfoSize = sizeof(TOsVersionInfoEx);
if( ! GetVersionEx(SVerInfo.old)) return GetWindowsVersion();
String S = GetWindowsVersion();
Sdop = "MoflM(])HKauMa " + (String)Verlnfo.old.szCSDVersion + ' ' + IntToStr(Verlnfo.old.dwBuildNumber) + "\r\n";
switch (Verlnfo.wProductType) { . case VER_NT_WORKSTATION:
if (S.SubStringd, S.PosC,') - 1) == "Windows NT") Sdop = Sdop +
"OnepaunoHHaa cucreMa Windows NT 4.0 Workstation.\r\n";
else if (S.SubStringd, S.PosC,') - 1) == "Windows 2000") Sdop = Sdop +
"OnepauMOHHaH cMcreMa Windows 2000 Professional.\r\n";• else if (S.SubStringd, S.PosC,') - 1) == "Windows XP") Sdop =.Sdop + .
"OnepauMOHHafl cncieMa Windows XP Professional.\r\n";
break;
case VER_NT_DOMAIN_CONTROLLER:-Sdop = Sdop + '
"OnepauMOHHaa cucTeMa HBJiaeTCH KOHTpoJi-nepOM " +' ' "flOMeHa.\r\n";
break;
case VER_NT_SERVER: ' ' ' • Sdop = Sdoo + "OnepauHOHHaH,'cucTeMa HBJiaeTCH cepBepOM..\r\n";
>if ^(VerInfO.wSuiteMask & VER_SUITE_BACKOFF.ICE > 0) Sdop = Sdop +
"ycTaHOBJieH KOMnoaeHT Microsoft BackOffice.\r\n";
if (Verlnfo.wSuiteMask & VER_SUITE_BLADE > 0) Sdop = Sdop +
"ycraHOBJieH KOMnoHeHT Windows .NET Web Server.\r\n";
if (Verlnfo.wSuiteMask S VER_SUITE_DATACENTER > 0) Sdop = Sdop +
"ycTaHOB-neHbi Windows 2000 .hjim KOMnoHeHT Windows " + ".NET-Datacenter Server.\r\n";
if (Verlnfo.wSuiteMask & VER_SUITE_DATACENTER > 0)
Sdop = Sdop + "ycraHOBJieH Windows 2000 Advanced Server " + "mjim KOMnoHeHT Windows .NET Enterprise Server.\r\n";
if (Verlnfo.wSuiteMask & VER_SUITE_PERSONAL > 0) Sdop = Sdop + '
"ycTaHOB.neHa"BepcKia Windows XP Home Edition. \r\n";
•if (Verinfo.wSuiteMask &1VER_SUITE_SMALLBUSINESS > 0) Sdop = Sdop +
"ycraHOBJieH Microsoft Small Business Server.\r\n";
if (Verlnfo.wSuiteMask & VER_SUITEJSMALLBUSINESS_RESTRICTED
> 0) Sdop = Sdop + "ycTaHOBJieH Microsoft Small. Business " +
"Server c orpaHMqureJibHOM ;nMueH3neti flJia miMeHTOB. \r\n";
if (Verlnfo.wSuiteMask & VER_SUITE_TERMINAL > 0)
Sdop = Sdop + "ycraHOBJieH KOMnoHeHT Terminal Services.\r\n";
return S;
}
void_fastcall TFormI::Button4Click(TObject *Sender) {
String Sdop;
Memol->Clear();
Memol->Lines->Add(GetWindowsVersionExEx(Sdop));
if(Sdop != "") Memol->Lines->Add(Sdop);
Memol->SelStart - 1;
Memol->Perform(EM_SCROLLCARET, 0, 0);
Работа с функцией GetVersionEx с использованием записи типа TOsVersionInfoEx оформлена в виде функции GetWindowsVersionExEx. Она возвращает строку характеристики операционной системы, вызывая описанную ранее функциюGetWindowsVersion. А если удается, то в параметрSdopвозвращается строка дополнительной информации. Схема работы с функциейGetVersionExс использованием записи типаTOsVersionInfoExвыглядит так. Объявляется типTOsVersionInfoExтак, как показано в приведенном коде. Полеold— это запись рассмотренного ранее типаTOsVersionInfo. А остальные поля записи позволяют получить дополнительную информацию об операционной системе, как видно из приведенного кода.
Перед вызовом GetVersionExв полеdwOSVersionInfosizeзаписи, на которую указывает полеold, заносится размер записиTOsVersionInfoEx(обратите внимание, именноTOsVersionInfoEx, а неTOsVersionInfo). Таким образом, отводится место для дополнительной информации. Далее следует вызовGetVersionExс передачей в него записи из поляold. Если вызов закончился неудачей, значит, версия соответствующей системнойDLL. не поддерживает выдачу расширенной информации. В этом случае вызывается описанная ранее функцияGetWindowsVersion, возвращающая стандартную информацию о системе, и выполнение завершается. Если же вызовGetVersionExпрошел успешно, то после получения стандартной информации вызовом функцииGetWindowsVersionследует анализ полейwProductTypeиwSuiteMaskзаписи типаTOsVersionInfoExи в. параметрSdopзаносится дополнительная информация о системе. ПараметрwSuiteMaskявляется комбинацией флагов, определяющих наличие некоторых компонентов операционной системы. Их смысл, вероятно, ясен из приведенного кода.
