Системная информация о компьютере
1. Введение.
В статье рассматриваются способы получения системной информации о компьютере (операционная система, статус памяти, процессор и др.) Большинство примеров опирается на Windows API. Робота их подразумевается только под WIN32 (лишь отдельные функции работают под WIN32s). Статья направлена на аудиторию программистов Delphi, но может быть полезна программистам и других сред разработки приложений, интересующимся API и системной информацией. В статье использованы документы сайта http://apiwallst.ru/ , а также коды:
- SysInfo Component, Angel's;
- TSysInfo Component, RicoSoft;
- TSYSINFO 2.1, Brent Boswell.
Главы о памяти и процессах ранее мной публиковались в интернете. Здесь они представлены с незначительными изменениями. Остальные главы публикуются впервые.
2. Состояние памяти.
Для получения детальной информации о состоянии памяти компьютера предназначена функция API GlobalMemoryStatus. В функцию передается переменная типа TMemoryStatus, которая представляет собой запись, тип которой определен следующим образом:
type
TMemoryStatus = record
dwLength: DWORD;
dwMemoryLoad: DWORD;
dwTotalPhys: DWORD;
dwAvailPhys: DWORD;
dwTotalPageFile: DWORD;
dwAvailPageFile: DWORD;
dwTotalVirtual: DWORD;
dwAvailVirtual: DWORD;
end;
Поля записи имеют следующий смысл:
dwLength | Длина записи. Поле необходимо инициализировать функцией SizeOf до обращения к функции GlobalMemoryStatus. |
dwMemoryLoad | Количество использованной памяти в процентах. |
dwTotalPhys | Число байт установленной на компьютере ОЗУ (физической памяти). |
dwAvailPhys | Свободная физическая память в байтах. |
dwTotalPageFile | Общий объем в байтах, который могут сохранить файлы/файл подкачки (вообще говоря, не совпадает с размером последних). |
dwAvailPageFile | Доступный объем из последней величины в байтах. |
dwTotalVirtual | Общее число байтов виртуальной памяти, используемой в вызывающем процессе. |
dwAvailVirtual | Объем виртуальной памяти, доступной для вызывающего процесса. |
Можно использовать следующий код получения информации о наличной памяти ОЗУ:
function GetRAM: Cardinal;
var MS: TMemoryStatus;
begin
MS.dwLength:=SizeOf(MS);
GlobalMemoryStatus(MS);
Result:=MS.dwTotalPhys;
end;
Пользовательская функция GetRAM возвращает общее число байт физической памяти, установленной на компьютере. Эту информацию она читает из поля dwTotalPhys записи MS, имеющей тип TMemoryStatus. Перед этим вызывается API-функция GlobalMemoryStatus с параметром MS. Обратите внимание, что перед вызовом GlobalMemoryStatus инициализируется поле dwLength функцией SizeOf.
По аналогии с примером можно получить информацию об остальных параметрах памяти, для этого надо заменить строку Result:=MS.dwTotalPhys на одну из перечисленных ниже:
Result:=MS.dwMemoryLoad;
Result:=MS.dwAvailPhys;
Result:=MS.dwTotalPageFile;
Result:=MS.dwAvailPageFile;
Result:=MS.dwTotalVirtual;
Result:=MS.dwAvailVirtual;
3. Информация о процессоре.
Функция GetSystemInfo с единственным параметром типа записи TSystemInfo дает доступ к различной системной информации. В частности, уровень процессора можно узнать из поля записи TSystemInfo – wProcessorLevel. Соответствие значений поля и основных уровней процессора приведено в таблице:
Значение поля wProcessorLevel | Уровень процессора |
---|---|
3 | 80386 |
4 | 80486 |
5 | Pentium |
6 | Pentium Pro |
Следующая пользовательская функция определяет уровень процессора:
function GetProcessorLevel: String;
var SI: TSystemInfo;
begin
GetSystemInfo(SI);
Case SI.wProcessorLevel of
3: Result:='80386';
4: Result:='80486';
5: Result:='Pentium';
6: Result:='Pentium Pro'
else Result:=IntToStr(SI.wProcessorLevel);end;
end;
Тактовую частоту процессора можно вычислить на основе следующего кода, использующего Ассемблер. Я его заимствовал, он хорошо работает, деталей реализации не знаю - привожу его без комментариев:
function GetCPUSpeed: Double;
const DelayTime = 500;
var TimerHi : DWORD;
TimerLo : DWORD;
PriorityClass : Integer;
Priority : Integer;
begin
PriorityClass := GetPriorityClass(GetCurrentProcess);
Priority := GetThreadPriority(GetCurrentThread);
SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
Sleep(10);
asm
DW 310Fh // rdtsc
MOV TimerLo, EAX
MOV TimerHi, EDX
end;
Sleep(DelayTime);
asm
DW 310Fh // rdtsc
SUB EAX, TimerLo
SBB EDX, TimerHi
MOV TimerLo, EAX
MOV TimerHi, EDX
end;
SetThreadPriority(GetCurrentThread, Priority);
SetPriorityClass(GetCurrentProcess, PriorityClass);
Result := TimerLo / (1000.0 * DelayTime);
end;
Данная пользовательская функция возвращает тактовую частоту процессора.
4. Информация о дисках.
Функция GetDriveType возвращает значение, по которому можно определить тип диска. Аргумент функции – буква, связанная с диском. Возвращаемые функцией значения и их смысл приведены в таблице:
Возвращаемое значение | Смысл |
---|---|
0 | Неизвестный |
1 | Не существует |
Drive_Removable | Съемный |
Drive_Fixed | Постоянный |
Drive_Remote | Внешний |
Drive_CDROM | Привод CD |
Drive_RamDisk | Диск RAM |
Следующая пользовательская функция иллюстрирует использование функции GetDriveType. По букве диска она определяет тип диска и возвращает последний в строку:
function GetDrive(Drive: String): String;
var
DriveType : uInt;
begin
DriveType := GetDriveType(PChar(Drive));
case DriveType of
0: Result := '?';
1: Result := 'Path does not exists';
Drive_Removable: Result := 'Removable';
Drive_Fixed: Result := 'Fixed';
Drive_Remote: Result := 'Remote';
Drive_CDROM: Result := 'CD-ROM';
Drive_RamDisk: Result := 'RAMDisk'
else Result := 'Unknown';
end;
end;
Для определения размера диска служит функция DiskSize. Параметр, который в нее передается – номер диска (0 – текущий, далее по порядку: 1 – A, 2 – B и т.д.). Для получения размера в Мегабайтах можно использовать следующую пользовательскую функцию:
function GetDriveSize(Num: Byte): String;
begin
if DiskSize(Num) <> -1 then
Result := format('%d MB', [Trunc(DiskSize(Num)/1024/1024)])
else
Result := '';
end;
При ошибке ответ – пустая строка.
5. Операционная система.
Информация об операционной системе хранится в записи типа TOSVersionInfo, выглядещей следующим образом:
type
TOSVersionInfo = record
dwOSVersionInfoSize: DWORD;
dwMajorVersion: DWORD;
dwMinorVersion: DWORD;
dwBuildNumber: DWORD;
dwPlatformId: DWORD;
szCSDVersion: array [0..126] of AnsiChar;
end;
Поля записи имеют следующий смысл:
dwOSVersionInfoSize | Размер записи. |
dwMajorVersion | Старший номер версии ОС. |
dwMinorVersion | Младший номер версии ОС. |
dwBuildNumber | Номер сборки ОС (в нижнем слове поля). |
dwPlatformId | Платформа. |
szCSDVersion | Строка поддержки для использования PSS. Содержит дополнительную информацию об ОС. Чаще всего – это пустая строка. |
Поле dwPlatformId может иметь следующие значения:
Ver_Platform_Win32s | Win32s в Windows 3.1 |
Ver_Platform_Windows | Win32 в Windows 95 |
Ver_Platform_Win32_NT | Windows NT |
Получить информацию об ОС позволяет API-функция GetVersionEx с единственным параметром типа TOSVersionInfo. Приведу пример ее использования:
function GetOS(var MajVer:Byte; var MinVer:Byte; var BuildNo:Word):String;
var VI: TOSVersionInfo;
begin
VI.dwOSVersionInfoSize:=SizeOf(VI);
GetVersionEx(VI);
MajVer:= VI.dwMajorVersion;
MinVer:= VI.dwMinorVersion;
BuildNo:= LoWord(VI.dwBuildNumber);
Result:= 'OS Version '+
IntToStr(MajVer)+'.'+
IntToStr(MinVer)+' build No '+
IntToStr(BuildNo);
end;
Пользовательская функция GetOS выводит строку с номером версии ОС. Обратите внимание, что перед вызовом GetVersionEx инициализируется поле dwOSVersionInfoSize функцией SizeOf.
Другой вариант реализации пользовательской функции получения информации о версии ОС может быть, например, таким (здесь используется дополнительная информация о системе из поля szCSDVersion):
function GetOS_2: string;
var
OSVersion: TOSVersionInfo;
begin
OSVersion.dwOSVersionInfoSize := SizeOf(OSVersion);
if GetVersionEx(OSVersion) then
Result:= Format('%d.%d (%d.%s)',
[OSVersion.dwMajorVersion, OSVersion.dwMinorVersion,
(OSVersion.dwBuildNumber and $FFFF), OSVersion.szCSDVersion]);
end;
Следующая пользовательская функция выводит версию платформы:
function GetPlatform: String;
var VI: TOSVersionInfo;
begin
VI.dwOSVersionInfoSize:=SizeOf(VI);
GetVersionEx(VI);
Case VI.dwPlatformId of
Ver_Platform_Win32s: Result:= 'Win32s';
Ver_Platform_Win32_Windows: Result:='Win95';
Ver_Platform_Win32_NT: Result:='WinNT'
else Result:='Unknown Platform'; end;
end;
6. Информация об основных каталогах.
Три функции дают пути к трем основным каталогам: GetWindowsDirectory – к каталогу ОС, GetSystemDirectory – к системной папке ОС и GetCurrentDirectory – к текущей папке. Эти функции имеют два параметра – путь к папке и размер его представления в памяти.
Следующая пользовательская функция иллюстрируют применение функции GetWindowsDirectory для получения пути к каталогу Windows:
function GetWindowsDir: string;
var S: array[0..MAX_PATH] of Char;
begin
GetWindowsDirectory(S,SizeOf(S));
Result:=S;
end;
Для получения пути к системной папке в вышеприведенном примере вместо строки GetWindowsDirectory(S,SizeOf(S)) надо использовать GetSystemDirectory(S,SizeOf(S)), а для получения пути к текущему каталогу - GetCurrentDirectory(SizeOf(S),S). Комментарии тут, думаю, излишни. Замечу только, что в обращении к функции GetCurrentDirectory первым параметром стоит размер пути, в отличие от двух других функций, где он на втором месте.
7. Информация о пользователе и компьютере.
Имя компьютера позволяет получить функция GetComputerName. В нее передается два параметра – параметр типа PChar, в который записывается имя компьютера и второй параметр, определяющий длину записи под имя. Следующая пользовательская функция выводит имя компьютера в строку:
function GetCompName: String;
var
i: DWORD;
p: PChar;
begin
i:=255;
GetMem(p, i);
GetComputerName(p, i);
Result:=String(p);
FreeMem(p);
end;
Очень похожим способом получается имя пользователя из функции GetUserName: