Salvador
Salvador

Reputation: 16472

How I can get the maximum memory size supported by a laptop or desktop machine?

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

Answers (2)

RRUZ
RRUZ

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

RRUZ
RRUZ

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

Related Questions