Шрифт:
Одним из способов узнать версию Windows является использование API-функции GetVersionEx. Она принимает в качестве параметра структуру OSVERSIONINFO (или OSVERSIONINFOEX, но об этом позже), заполняет поля этой структуры и в случае удачи возвращает ненулевое значение.
Объявление ANSI-версии структуры OSVERSIONINFO в библиотеке Delphi 7 выглядит следующим образом:
OSVERSIONINFOA = record
dwOSVersionInfoSize: DWORD; //Размер структуры
dwMajorVersion: DWORD; //Старшая часть версии ОС Windows
dwMinorVersion: DWORD; //Младшая часть версии
dwBuildNumber: DWORD; //Номер сборки операционной системы
dwPlatformId: DWORD; //Идентификатор платформы Windows
szCSDVersion: array[0..127] of AnsiChar; //Дополнительные
//сведения, например, установленный пакет обновлений
end;
Не будем вдаваться в подробное описание возможных значений полей этой структуры: практически все будет ясно из приведенного далее примера. Напомним лишь, чтобы вы не забывали заполнять поле dwOSVersionInf oSize перед вызовом функции GetVersionEx.
Итак, пример обработки данных, помещаемых в структуру OSVERSIONINFO, приведен в листинге 7.1. При загрузке формы элемент управления ListView с именем lvwVerlnf о заполняется сведениями о версии системы, представленными в читабельной форме.
Листинг 7.1.
Получение и отображение сведений о Windows
procedure TForm1.FormCreate(Sender: TObject);
var
info: OSVERSIONINFO;
item: TListItem;
begin
//Получаем информацию о версии ОС
info.dwOSVersionInfoSize := SizeOf(info);
GetVersionEx(info);
//Заполняем список информацией о ОС
//..версия ОС
item := lvwVerInfo.Items.Add;
item.Caption := \'Версия системы\
item.SubItems.Insert(0, IntToStr(Integer(info.dwMajorVersion)) +
\'.\' + IntToStr(Integer(info.dwMinorVersion)));
//..номер сборки
item := lvwVerInfo.Items.Add;
item.Caption := \'Сборка\
item.SubItems.Insert(0, IntToStr(Integer(info.dwBuildNumber)));
//..платформа
item := lvwVerInfo.Items.Add;
item.Caption := \'Платформа\
case info.dwPlatformId of
VER_PLATFORM_WIN32s:
//Эмуляция Win32 или Win16
item.SubItems.Insert(0, \'Win16\');
VER_PLATFORM_WIN32_WINDOWS:
//"Классическая" Win32: 95, 98 или Me
item.SubItems.Insert(0, \'Win32\');
VER_PLATFORM_WIN32_NT:
//Ядро NT
item.SubItems.Insert(0, \'WinNT\');
end;
//..дополнительная информация (например, пакет обновлений)
item := lvwVerInfo.Items.Add;
item.Caption := \'Дополнительные сведения\
item.SubItems.Insert(0, info.szCSDVersion);
end;
Возможный результат работы программы (для Windows ХР SP1) приводится на рис. 7.1.
Рис. 7.1. Информация о версии Windows
Теперь снова обратимся к функции GetVersionEx, точнее говоря, к структуре OSVERSIONINFOEX, которая может также передаваться в качестве параметра в функцию. К сожалению, в библиотеке Delphi 7 эта структура не объявлена. Но это можно сделать самостоятельно:
OSVERSIONINFOEX = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array[0..127] of AnsiChar;
//Поля, которых нет в OSVERSIONINFO
wServicePackMajor: WORD; //Старшая цифра версии пакета
//обновлений
wServicePackMinor: WORD; //Младшая цифра версии пакета
//обновлений
wSuiteMask: WORD; //Комплектация системы
wProductType: BYTE; //Дополнительная информации об ОС
wReserved: BYTE;
end;
Дополнительные (по сравнению с OS VERS ION INFO) поля структуры может заполнить ОС Windows NT 4.0 SP6 и более поздние версии Windows NT (в том числе 2000 и ХР). Значения дополнительных полей структуры OSVERSIONINFOEX пояснены комментариями в объявлении структуры.
Значение поля wSuiteMask (является битовой маской) может быть составлено из значений следующих констант (увы, но их объявления также пришлось добавить самостоятельно).
VER_SUITE_BACKOFFICE = 4; //Установлена Microsoft Back Office
VER_SUITE_DATACENTER = 128;//Установлена Microsoft Data Center
VER_SUITE_ENTERPRISE = 2; //Установлена ОС Windows 2000
//Advanced Server
VER_SUITE_SMALLBUSINESS = 1; //Установлена Microsoft Small
//Business Server
VER_SUITE_SMALLBUSINESS_RESTRICTED = 32; //Установлена
//ограниченная версия Microsoft
//Small Business Server
VER_SUITE_TERMINAL = 16; //Установлены терминальные службы
VER_SUITE_PERSONAL = 512; //Персональная версия ОС (типичный
//набор функций меньше, чем в Professional)
Значение поля wProductType может быть одним из приведенных ниже (тип сетевой ОС и соответственно роль, которую компьютер с данной ОС может исполнять при подключении в сети):
VER_NT_WORKSTATION = 1; //Рабочая станция
VER_NT_DOMAIN_CONTROLLER = 2; //Контроллер домена
VER_NT_SERVER = 3; //Сервер
Чтобы можно было просто передавать в функцию GetVersionEx ссылку на структуру OSVERSIONINFOEX, а не OSVERSIONINFO, перегрузим эту функцию следующим образом:
function GetVersionEx(var lpVersionInformation: OSVERSIONINFOEX): BOOL;
stdcall; external kernel32 name \'GetVersionExA\
Теперь определение полной информации о версии ОС для случая Windows на платформе NT (выше NT 4.0 SP6) может выглядеть следующим образом (листинг 7.2) (часть, одинаковая с листингом 7.1, опущена).
Листинг 7.2.
Определение версии ОС (NT, 2000, ХР)
procedure TForm1.FormCreate(Sender: TObject);
var
info: OSVERSIONINFOEX;
item: TListItem;
suite, additional: String;
begin
//Получаем информацию о версии ОС
info.dwOSVersionInfoSize := SizeOf(info);
GetVersionEx(info);
//Заполняем список информацией об ОС
//…
//..версия о пакете обновлений
item := lvwVerInfo.Items.Add;
item.Caption := \'Версия ServicePack\
item.SubItems.Insert
(0, IntToStr(Integer(info.wServicePackMajor)) + \'.\' +
IntToStr(Integer(info.wServicePackMinor)));
//..комплекация ОС
suite := \'\
if info.wSuiteMask and VER_SUITE_BACKOFFICE <> 0 then
suite := suite + \'[Установлен Back Office] \
if info.wSuiteMask and VER_SUITE_DATACENTER <> 0 then
suite := suite + \'[Microsoft Data Center] \
if info.wSuiteMask and VER_SUITE_ENTERPRISE <> 0 then
suite := suite + \'[Windows 2000 Advanced Server] \
if info.wSuiteMask and VER_SUITE_SMALLBUSINESS <> 0 then
suite := suite + \'[Small Business Server] \
if info.wSuiteMask and VER_SUITE_SMALLBUSINESS_RESTRICTED <> 0
then
suite := suite + \'[Small Business Server, ограниченная версия] \
if info.wSuiteMask and VER_SUITE_TERMINAL <> 0 then
suite := suite + \'[Terminal Service] \
if info.wSuiteMask and VER_SUITE_PERSONAL <> 0 then
suite := suite + \'[Workstation Personal (не Professional)] \
item := lvwVerInfo.Items.Add;
item.Caption := \'Комплектация\
item.SubItems.Add(suite);
//..дополнительные сведения
additional := \'\
if info.wProductType and VER_NT_WORKSTATION <> 0 then
additional := additional + \'[Рабочая станция] \
if info.wProductType and VER_NT_DOMAIN_CONTROLLER <> 0 then
additional := additional + \'[Контроллер домена] \
if info.wProductType and VER_NT_SERVER <> 0 then
additional := additional + \'[Сервер] \
item := lvwVerInfo.Items.Add;
item.Caption := \'Дополнительно\
item.SubItems.Add(additional);
end;
Имя компьютера
Следующий простой пример (листинг 7.3) показывает, как можно определить сетевое имя компьютера. Функция ComputerName скрывает «прелести» работы со строковым буфером, который нужно передавать в API-функцию GetComputerName.
Листинг 7.3.
Определение сетевого имени компьютера
function ComputerName: String;
var
buffer: String;
len: Cardinal;
begin
len := MAX_COMPUTERNAME_LENGTH + 1;
SetLength(buffer, len);
if GetComputerName(PAnsiChar(buffer), len) <> False then
ComputerName := Copy(buffer, 1, len)
else
ComputerName := \'\
end;