Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Определение количества RAM и количества видеопамяти (http://forum.oszone.net/showthread.php?t=161171)

stasmd 23-12-2009 02:14 1302156

Определение количества RAM и количества видеопамяти
 
Встала проблема в определении количества оперативки и памяти видеокарты.
Код ест, однако он не совсем верно пашет

Код:

function raminfo:PChar;
var MemInfo:TMemoryStatus;
begin
  MemInfo.dwLength:=SizeOf(MemInfo);  // Определяет актуальную информацию о памяти
  GlobalMemoryStatus(MemInfo);
result:=PChar(IntToStr(MemInfo.dwTotalPhys div 1047500)+' Mb ');  // высчтывает ее
end;

и для видеокарты
Код:

// РАМ на видюхе 2
function vidmeminfo2:PChar;
var
  lpDisplayDevice: TDisplayDevice;
  a:Real;
  b:string;
begin
lpDisplayDevice.cb := sizeof(lpDisplayDevice);
EnumDisplayDevices(nil, 0, lpDisplayDevice, 0);
a:=(lpDisplaydevice.StateFlags div 524280);
//a:=Round(Int(a));
b:=FloatToStr(a);
Result:=Pchar(b+' ');
end;

Функция памяти определяет нормально только до 2 Гб оперативки, все что более определяется не верно (обычно как 2047). На x64 не тестил, может там будет пахать.

Память видеокарты фиксировано выдает 256 Мб на любой конфигурации.


Знаю что prokazzza, и Mr dUSHA как то сделали такое в WinStyle. Не знаю что делать, почти месяц стою на этой проблеме...

Admiral 23-12-2009 02:22 1302158

stasmd, правильно, до двух гигх, как и сказано в документации. Исключения, если программа скомпилирована с ключом /LARGEADDRESSAWARE (для Сишного компилятора Микрософт), тогда и с этой потянет. Для большего нужно воспользоваться функцией GlobalMemoryStatusEx, да и вовсе, не Ex функция устарела.

Кстати MemInfo.dwLength:=SizeOf(MemInfo); означает элементу dwLength структуры MemInfo присвоить размер типа переменной MemInfo, что по сути SizeOf(TMemoryStatus).
Если конечно комментарий в коде не относиться глобально к участку кода, а к данной строке.

Насчёт видео, то данная функция (EnumDisplayDevices) не предназначена для получения количества видеопамяти. К тому же параметр DeviceString, структуры TDisplayDevice (DISPLAY_DEVICE), несёт имя устройства вывода...

stasmd 23-12-2009 03:33 1302181

Цитата:

Цитата Admiral
SizeOf(TMemoryStatus) »

Не совсем с этим понятно. То есть это замена
Код:

MemInfo.dwLength:=SizeOf(MemInfo);
как я понял.


Насчет памяти, дал не тот код :)
Вот нужный, но он не работает как следует
Код:

// РАМ на видюхе 2
function vidmeminfo2:PChar;
var
  lpDisplayDevice: TDisplayDevice;
  a:Real;
  b:string;
begin
lpDisplayDevice.cb := sizeof(lpDisplayDevice);
EnumDisplayDevices(nil, 0, lpDisplayDevice, 0);
a:=(lpDisplaydevice.StateFlags div 524280);
//a:=Round(Int(a));
b:=FloatToStr(a);
Result:=Pchar(b+' ');
end;


Admiral 23-12-2009 17:32 1302669

stasmd да, так MemInfo.dwLength:=SizeOf(TMemoryStatus); будет более читабельно. Это же касается и приведённого кода для видео - lpDisplayDevice.cb := sizeof(TDisplayDevice);
Хоть основное внимание в предыдущем посте было уделено уточнению комментария, объясняющему данную строку в первом посте.

Обновлённый код не меняет утверждение
Цитата:

функция (EnumDisplayDevices) не предназначена для получения количества видеопамяти
Что за константа 524280?
1024*1024 = 1048576 (это если константа выше призвана переводить из байтов в МБ, то откуда она именно такая?)
StateFlags - означает, как это ни банально, статус устройства вывода и может быть комбинацией значений
DISPLAY_DEVICE_ACTIVE\DISPLAY_DEVICE_MIRRORING_DRIVER\DISPLAY_DEVICE_MODESPRUNED\DISPLAY_DEVICE_PRIM ARY_DEVICE\DISPLAY_DEVICE_REMOVABLE\DISPLAY_DEVICE_VGA_COMPATIBLE
DISPLAY_DEVICE Structure
В данном случаи в StateFlags - 256*524280 = 134215680. Но так как 524280 не делит истинное значение без остатка, на самом деле StateFlags содержит 134217733 и означает
Код:

DISPLAY_DEVICE_ACTIVE
DISPLAY_DEVICE_MODESPRUNED
DISPLAY_DEVICE_PRIMARY_DEVICE


stasmd 23-12-2009 18:51 1302761

Admiral, код брал на Делфи Кингдом, сам я не особо врубился в его значение.
Насчет видео, то ясно чего не не выдавал :)

Константа подбиралась под количество рам на моей видяхе (но как оказалось бестолку)


Далее с оперативкой, функция GlobalMemoryStatusEx не пашет, нету ее на делфи :(
Путался методом копипаста добаить, но бестолку
Код:

[Error] KMSI.dpr(33): Undeclared identifier: 'GlobalMemoryStatusEx'
вот сам код
Код:

function TotalPhysicalMemory: Int64;
var
  MemoryStatus: TMEMORYSTATUSEX;
begin
    MemoryStatus.dwLength := SizeOf(MemoryStatus);
    if GlobalMemoryStatusEx(MemoryStatus) then
      Result := MemoryStatus.ullTotalPhys
    else
      Result := 0;
end;

переменные выше описаны, кидать сюда их не стал.

Admiral 23-12-2009 18:57 1302763

stasmd, увы, по вопросу непосредственно кода Делфи подсказать не смогу, предыдущее рекомендации говорил, проводя аналогию с Си.
Вот есть тема на codegear по данной функции
Problem with GlobalMemoryStatusEx()
Предлагают описать функцию самостоятельно, в системе то она есть.

stasmd 23-12-2009 20:06 1302792

Admiral, тему видел, но все равно спасибо.

А насчет определения видеопамяти ничего подсказать не сможете?

Admiral 23-12-2009 22:28 1302904

stasmd, сложно сказать, мне такая функция, в рамках WIN32, не известна, иначе бы обязательно дал знать.
Не исключаю, что в системе можно что-то поискать, и найти, к примеру, в реестре запись про
видеопамять. А для актуального определения видеопамяти (в реестре данные могут устаревать/быть не точными), придётся связываться с графическими библиотеками.
Например с DirectX
(и с тамтешней технологией COM\COM+)
В комплекте DxSDK есть одноимённый пример Samples\C++\Misc\VideoMemory
В примере приводится определения доступной видео памяти. Наиболее точное значение (адекватной свободной) вернул GetVideoMemoryViaDirectDraw (это не название функции, а сообщения в консоли при выполнении программы из этого примера)
GetVideoMemoryViaD3D9 не понятно как считает, вернул число больше чем физически видеопамяти в системе. Вероятно как-то учитывает и ОЗУ. Остальные вообще вернули n/a


Но это зависит от приложения, если оно уже использует графическую библиотеку, то проблем быть не должно, и ответ ждёт в документации к последней.
А для не использующих, не совсем ясно, зачем выявление этого значение вовсе нужно? Разве что для написания своего Эвереста, SiSoft Sandr и подобного софта.

P.S.
Может быть если работать с API драйверов, например с функцией DrvGetDirectDrawInfo, можно узнать и количество видеопамяти.

stasmd 24-12-2009 00:15 1302985

Admiral, с технологией КОМ не знаком :)
Собственно видеопамять можно считывать из реестра, но... Непонятно где она хранится, так как все что можно было я обыскал.

Что интересно, как отписался в первом посте,
Цитата:

Знаю что prokazzza, и Mr dUSHA как то сделали такое в WinStyle
У них видеопамять определяется.

Ну определение видеопамяти не столь критично для меня.


Насчет оперативки, то функция GlobalMemoryStatusEx пашет не совсем корректно.
Не выдает все нужное количество RAM

Admiral 24-12-2009 00:51 1303005

Вот здесь HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\VIDEO перечислены устройства вывода, указанны дальнейшие адреса по поиску.
У меня для \Device\Video0 указанно
\Registry\Machine\System\CurrentControlSet\Control\Video\{8A1E77B7-6F63-41CF-96DA-69F860EB4DDC}\0000
Это естественно означает HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video\{8A1E77B7-6F63-41CF-96DA-69F860EB4DDC}\0000
Там есть ключ HardwareInformation.MemorySize, значение правда там какое-то левое, и ничего общего с реальностью не имеет.


GlobalMemoryStatusEx проверил на ПК с 512 МБ, всё определилось правильно. Значение в dwLength перед вызовом функции заданно?

stasmd 24-12-2009 17:18 1303459

Admiral, насчет ключей реестр а знаю, уже думал над этим, но на разных компах {8A1E77B7-6F63-41CF-96DA-69F860EB4DDC}\0000 это значение разное.


Вот код для определения RAM (убил вчера часа 3 перепробовал массу вариантов и вариаций написания)

Код:

// общий размер физической памяти
function raminfo: PChar;
var
  MemoryStatus: TMemoryStatusEx;
begin
//ZeroMemory(@MemoryStatus, SizeOf(TMemoryStatusEx));
MemoryStatus.dwLength := SizeOf(TMemoryStatusEx);
GlobalMemoryStatusEx(MemoryStatus);
Result :=PChar(IntToStr(MemoryStatus.ullTotalPhys div 5441471906132)+' Mb '); //не обращать внимания, пытался подстроить под себя
if Result<>' ' then
Result:=Result
else
Result:=PChar('Нет Данных');
end;


Admiral 25-12-2009 20:58 1304289

stasmd
Цитата:

HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\VIDEO
будет на всех ПК, а там в параметрах
Цитата:

указанны дальнейшие адреса по поиску
программно.
Но смысла в них нет, так как в HardwareInformation.MemorySize что-то не то.

Drongo 25-12-2009 21:36 1304332

stasmd, Admiral, Извините что вмешиваюсь, мне когда-то Serega помогал инсталятор делать, в котором была проверка видеопамяти. Может это поможет чем-то? :dont-know Здесь идёт определение модели видеокарты, размера памяти и текущее разрешение.
Код:

// Видеокарта:
  VideoRAMPanel.Color := $CCFFCC

  lpDisplayDevice.cb := SizeOf(lpDisplayDevice)
  DeviceKey := ''
        n := 0
  while not (EnumDisplayDevices(0, n, lpDisplayDevice, 0) and
            (lpDisplayDevice.StateFlags and DISPLAY_DEVICE_PRIMARY_DEVICE > 0)) and (n < 127) do n := n + 1
        for n := 0 to 127 do DeviceKey := DeviceKey + lpDisplayDevice.DeviceKey[n]
  Delete(DeviceKey, Pos(Chr(0), DeviceKey), 127)  // Ключ драйвера получаем из API
        StringChange(DeviceKey, '\Registry\Machine\', '')
  errCode := 1
  DeviceValue := 0
  if RegQueryBinaryValue(HKLM, DeviceKey, 'HardwareInformation.MemorySize', DeviceName) then
                for n := 1 to Length(DeviceName) do
      begin
        DeviceValue := DeviceValue + Ord(DeviceName[n])*errCode
        errCode := errCode*$100
      end
  else
    if RegQueryDWordValue(HKLM, DeviceKey, 'HardwareInformation.MemorySize', DeviceValue) then
    else
        RegQueryDWordValue(HKLM, DeviceKey + '\Info', 'VideoMemory', DeviceValue)
        DeviceName := ''
  for n := 0 to 127 do DeviceName := DeviceName + lpDisplayDevice.DeviceString[n]
  Delete(DeviceName, Pos(Chr(0), DeviceName), 127)

  if DeviceName <> '' then
    if DeviceValue > 0 then
      VideoRAMPanel.Text := ' ' + DelSp(DeviceName) + ', '+ ByteOrTB(DeviceValue/oneMB, False)
    else
      VideoRAMPanel.Text := ' ' + DelSp(DeviceName) + ' (Standard), '+ ByteOrTB(DeviceValue/oneMB, False)
  else
    begin
      VideoRAMPanel.Text := ' Драйвер устройства не обнаружен'
      VideoRAMPanel.Color := $CCCCFF
      ChangeText := True
    end
  if (DeviceValue/oneMB < NeedVideoRAM) then
    begin
      VideoRAMPanel.Color := $CCCCFF
      ChangeText := True
    end
  VideoRAMPanel.Text := VideoRAMPanel.Text + ', ' + IntToStr(GetSystemMetrics(0)) + 'x' +
                        IntToStr(GetSystemMetrics(1)) + ' (' + IntToStr(GetDeviceCaps(CreateDC('DISPLAY','','',0),14) *
                        GetDeviceCaps(CreateDC('DISPLAY','','',0),12)) + ' bit)'


stasmd 26-12-2009 02:06 1304491

Drongo, вроде чето есть. Проверю сайчас, спасибо.

Admiral, а что с кодом для оперативки делать? Скиньте свой для сравнения.

PS Старый код без ЕХ прекрасно пашет на х64 :/

Admiral 26-12-2009 03:57 1304514

stasmd, у меня на Си
Код:

#include <windows.h>
#include <stdio.h>

int wmain(int argc, wchar_t *argv[])
{
        MEMORYSTATUSEX Buffer = {0};        //Объявляем переменную Buffer структурного типа MEMORYSTATUSEX
        Buffer.dwLength = sizeof(MEMORYSTATUSEX);        //Присваиваем элементу dwLength размер структуры MEMORYSTATUSEX
        GlobalMemoryStatusEx(&Buffer);        //Вызываем функцию определяющую количество установленной на ПК памяти
        wprintf(L"\n%ld", Buffer.ullTotalPhys);                //результат отобразить в консоли
        return 0;        //заканчиваем работу программы
}

Если сравнивать с постом №11 и не брать во внимание строку с делением то код такой же.
Инициализация MEMORYSTATUSEX Buffer = {0}; аналогична тому что далее будет вызвано ZeroMemmory, но в данном случаи главное заполнить dwLength перед вызовом GlobalMemoryStatusEx.

stasmd 01-04-2010 23:21 1382845

Вопрос - где в реестре Windows хранится значение текущей оперативной памяти? И храниться ли?

Drongo 02-04-2010 14:19 1383356

Цитата:

Цитата stasmd
И храниться ли? »

Думаю, что нет. Не хранится такое значение в реестре.

Admiral 05-04-2010 13:35 1385385

stasmd HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\System Resources\Physical Memory параметр .Translated
Хранится не в десятичной системе исчесления, а в неком REG_RESOURCE_LIST.
how to read REG_RESOURCE_LIST data from registry

На MS How to get the Physical Memory information using Registry рекомендуют всё же прислушатся к GlobalMemoryStatus(Ex)


Время: 11:11.

Время: 11:11.
© OSzone.net 2001-