Войти

Показать полную графическую версию : Определение количества RAM и количества видеопамяти


stasmd
23-12-2009, 02:14
Встала проблема в определении количества оперативки и памяти видеокарты.
Код ест, однако он не совсем верно пашет

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
stasmd, правильно, до двух гигх, как и сказано в документации. Исключения, если программа скомпилирована с ключом /LARGEADDRESSAWARE (для Сишного компилятора Микрософт), тогда и с этой потянет. Для большего нужно воспользоваться функцией GlobalMemoryStatusEx (http://msdn.microsoft.com/en-us/library/aa366589(VS.85).aspx), да и вовсе, не Ex функция устарела.

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

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

stasmd
23-12-2009, 03:33
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
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 (http://msdn.microsoft.com/en-us/library/dd183569(VS.85).aspx)
В данном случаи в StateFlags - 256*524280 = 134215680. Но так как 524280 не делит истинное значение без остатка, на самом деле StateFlags содержит 134217733 и означает
DISPLAY_DEVICE_ACTIVE
DISPLAY_DEVICE_MODESPRUNED
DISPLAY_DEVICE_PRIMARY_DEVICE

stasmd
23-12-2009, 18:51
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
stasmd, увы, по вопросу непосредственно кода Делфи подсказать не смогу, предыдущее рекомендации говорил, проводя аналогию с Си.
Вот есть тема на codegear по данной функции
Problem with GlobalMemoryStatusEx() (https://forums.codegear.com/thread.jspa?threadID=2502)
Предлагают описать функцию самостоятельно, в системе то она есть.

stasmd
23-12-2009, 20:06
Admiral, тему видел, но все равно спасибо.

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

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

Но это зависит от приложения, если оно уже использует графическую библиотеку, то проблем быть не должно, и ответ ждёт в документации к последней.
А для не использующих, не совсем ясно, зачем выявление этого значение вовсе нужно? Разве что для написания своего Эвереста (http://www.lavalys.com/), SiSoft Sandr'ы (http://www.sisoftware.net/) и подобного софта.

P.S.
Может быть если работать с API драйверов, например с функцией DrvGetDirectDrawInfo (http://msdn.microsoft.com/en-us/library/ms793204.aspx), можно узнать и количество видеопамяти.

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

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

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


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

Admiral
24-12-2009, 00:51
Вот здесь 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
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
stasmd HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\VIDEO будет на всех ПК, а там в параметрах указанны дальнейшие адреса по поиску программно.
Но смысла в них нет, так как в HardwareInformation.MemorySize что-то не то.

Drongo
25-12-2009, 21:36
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
Drongo, вроде чето есть. Проверю сайчас, спасибо.

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

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

Admiral
26-12-2009, 03:57
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
Вопрос - где в реестре Windows хранится значение текущей оперативной памяти? И храниться ли?

Drongo
02-04-2010, 14:19
И храниться ли? »Думаю, что нет. Не хранится такое значение в реестре.

Admiral
05-04-2010, 13:35
stasmd HKEY_LOCAL_MACHINE\HARDWARE\RESOURCEMAP\System Resources\Physical Memory параметр .Translated
Хранится не в десятичной системе исчесления, а в неком REG_RESOURCE_LIST.
how to read REG_RESOURCE_LIST data from registry (http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/84642bd4-1dc6-4ae9-bd64-d5e0d985e347)

На MS How to get the Physical Memory information using Registry (http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/0d467e1c-1b1c-4db5-9c2f-91bb47497068) рекомендуют всё же прислушатся к GlobalMemoryStatus(Ex)




© OSzone.net 2001-2012