Reputation: 16472
I'm building a software using Delphi to get some hardware info, I need to get the maximum memory (RAM) size supported by a laptop or desktop machine using delphi, so far I was looking for a WinApi or WMI function to get that info, but I not found any info related to this. How I can get the maximum memory size supported by a laptop or desktop machine?
Upvotes: 2
Views: 1254
Reputation: 136391
You can use the Win32_PhysicalMemoryArray
WMI class and the MaxCapacity property.
MaxCapacity : Maximum memory size (in bytes) installable for this particular memory array. If the size is unknown, the property is given a value of 0 (zero).
This property can return the size in bytes or kilobytes, so you must check the Units
qualifier of the property before to use it.
Try this sample
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Variants;
function GetQualifierValue(Const NameSpace, ClassName, PropName, QualifName : string) :string;
const
wbemFlagUseAmendedQualifiers = $00020000;
Var
Properties : OleVariant;
Qualifiers : OleVariant;
rgvarProp : OleVariant;
rgvarQualif : OleVariant;
objSWbemLocator : OleVariant;
objSWbemObjectSet : OleVariant;
objWMIService : OleVariant;
EnumProps : IEnumVariant;
EnumQualif : IEnumVariant;
pceltFetched : Cardinal;
Lindex : Integer;
begin
Result:='';
objSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
objWMIService := objSWbemLocator.ConnectServer('localhost', NameSpace, '', '');
objSWbemObjectSet:= objWMIService.Get(ClassName, wbemFlagUseAmendedQualifiers);
Properties := objSWbemObjectSet.Properties_;
EnumProps := IUnknown(Properties._NewEnum) as IEnumVariant;
while EnumProps.Next(1, rgvarProp, pceltFetched) = 0 do
begin
if SameText(rgvarProp.Name, PropName) then
begin
Qualifiers := rgvarProp.Qualifiers_;
EnumQualif := IUnknown(Qualifiers._NewEnum) as IEnumVariant;
while EnumQualif.Next(1, rgvarQualif, pceltFetched) = 0 do
begin
if SameText(QualifName, rgvarQualif.Name) then
begin
if not VarIsNull(rgvarQualif.Value) then
Result:=rgvarQualif.Value;
Break;
end;
rgvarQualif:=Unassigned;
end;
Break;
end;
rgvarProp:=Unassigned;
end;
end;
function GetMaxMemoryCapacity : UInt32;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
UnitsName : string;
begin;
Result:=0;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
UnitsName := GetQualifierValue('root\CIMV2','Win32_PhysicalMemoryArray','MaxCapacity','Units');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT MaxCapacity,MemoryDevices FROM Win32_PhysicalMemoryArray','WQL',$00000020);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
if SameText('kilobytes', UnitsName) then
Result:=Result+(UInt32(FWbemObject.MaxCapacity)*UInt32(FWbemObject.MemoryDevices))
else
Result:=Result+((UInt32(FWbemObject.MaxCapacity) div 1024)*UInt32(FWbemObject.MemoryDevices));
FWbemObject:=Unassigned;
end;
end;
Upvotes: 5
Reputation: 136391
You can use the SMBIOS to get that info, try reading the documentation about the Physical Memory Array (Type 16)
Table. You can parse and extract the SMBIOS tables manually or use a library like TSMBIOS.
try this sample which uses the TSMBIOS library.
{$APPTYPE CONSOLE}
uses
Classes,
SysUtils,
uSMBIOS in '..\..\Common\uSMBIOS.pas';
function GetMaxMemoryCapacity : UInt32;
Var
SMBios : TSMBios;
LPhysicalMemArr : TPhysicalMemoryArrayInformation;
begin
result:=0;
SMBios:=TSMBios.Create;
try
if SMBios.HasPhysicalMemoryArrayInfo then
for LPhysicalMemArr in SMBios.PhysicalMemoryArrayInfo do
begin
if LPhysicalMemArr.RAWPhysicalMemoryArrayInformation.MaximumCapacity<>$80000000 then
result:=result+(LPhysicalMemArr.RAWPhysicalMemoryArrayInformation.MaximumCapacity*LPhysicalMemArr.RAWPhysicalMemoryArrayInformation.NumberofMemoryDevices)
else
result:=result+((LPhysicalMemArr.RAWPhysicalMemoryArrayInformation.ExtendedMaximumCapacity div 1024)*LPhysicalMemArr.RAWPhysicalMemoryArrayInformation.NumberofMemoryDevices);
end
else raise Exception.Create('No Physical Memory Array Info was found');
finally
SMBios.Free;
end;
end;
begin
try
Writeln(Format('Max Memory Capacity installable %d kb',[GetMaxMemoryCapacity]));
except
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Upvotes: 6