Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I determine the amount of RAM?

System Information

How do I determine the amount of RAM?

by  Griffyn  Posted    (Edited  )
It's become more difficult to determine the amount of RAM in a system, since >2GB became more common, and some operating systems don't handle reporting of more than 2GB correctly. The following code should handle any combination of OS and RAM amount.

Code:
[navy][i]// for automatic syntax highlighting see faq102-6487 
[/i][/navy][b]uses[/b]
  Windows;
[b]type[/b]
  TMemoryStatusEx = [b]record[/b]
    dwLength: DWORD;
    dwMemoryLoad: DWORD;
    ullTotalPhys: Int64;
    ullAvailPhys: Int64;
    ullTotalPageFile: Int64;
    ullAvailPageFile: Int64;
    ullTotalVirtual: Int64;
    ullAvailVirtual: Int64;
    ullAvailExtendedVirtual: Int64;
  [b]end[/b];

[b]function[/b] GetGlobalMemoryRecord: TMemoryStatusEx;
[b]type[/b]
  TGlobalMemoryStatusEx = [b]procedure[/b]([b]var[/b] lpBuffer: TMemoryStatusEx); [b]stdcall[/b];
[b]var[/b]
  ms : TMemoryStatus;
  h : THandle;
  gms : TGlobalMemoryStatusEx;
[b]begin[/b]
  Result.dwLength := SizeOf(Result);
  h := LoadLibrary(kernel32);
  [b]try[/b]
    [b]if[/b] h <> [purple]0[/purple] [b]then[/b]
    [b]begin[/b]
      @gms := GetProcAddress(h, [teal]'GlobalMemoryStatusEx'[/teal]);
      [b]if[/b] @gms <> [b]nil[/b] [b]then[/b]
        gms(Result)
      [b]else[/b]
      [b]begin[/b]
        ms.dwLength := SizeOf(ms);
        GlobalMemoryStatus(ms);
        Result.dwMemoryLoad := ms.dwMemoryLoad;
        Result.ullTotalPhys := ms.dwTotalPhys;
        Result.ullAvailPhys := ms.dwAvailPhys;
        Result.ullTotalPageFile := ms.dwTotalPageFile;
        Result.ullAvailPageFile := ms.dwAvailPageFile;
        Result.ullTotalVirtual := ms.dwTotalVirtual;
        Result.ullAvailVirtual := ms.dwAvailVirtual;
      [b]end[/b]
    [b]end[/b];
  [b]finally[/b]
    FreeLibrary(h);
  [b]end[/b];
[b]end[/b];

[b]function[/b] GetTotalRAM: Int64;
[b]begin[/b]
  Result := GetGlobalMemoryRecord.ullTotalPhys;
[b]end[/b];

You can see from the record structure it is trivial to get other values from the system.

To ensure accurate reporting for systems that have between 2GB and 4GB of RAM, the /LARGEADDRESSAWARE flag must be set in the compiled .EXE. Delphi 6 and earlier don't have this as an option in the IDE, so you must include this line
Code:
[navy][i]{$SetPEFlags $0020}   { /LargeAddressAware }[/i][/navy]
in your .dpr (project source) file. Putting it in a unit, such as your main form unit is not enough as the linker will not include it unless the unit is recompiled.

I'm not sure if this option is included in D7 or above. Setting that option in the linker options if it's available should be enough.

One last code snippet to format the byte count to something more readable:
Code:
[navy][i]{ This function returns a formatted string with at the appropriate level of bytes, kilobytes, megabytes, gigabytes, etc }[/i][/navy]
[b]function[/b] FormatBytes(ABytes: Int64; AShortRounding: Boolean = True): String;
[b]const[/b]
  suffix : [b]array[/b][[purple]0..6[/purple]] [b]of[/b] String = ([teal]'B'[/teal], [teal]'KB'[/teal], [teal]'MB'[/teal], [teal]'GB'[/teal], [teal]'TB'[/teal], [teal]'PB'[/teal], [teal]'EB'[/teal]);
[b]var[/b]
  l : Integer;
  f : Double;
[b]begin[/b]
  l := [purple]0[/purple];
  f := ABytes;
  [b]while[/b] (l < High(suffix)) [b]and[/b] (f >= [purple]1024[/purple]) [b]do[/b]
  [b]begin[/b]
    inc(l);
    f := f / [purple]1024[/purple];
  [b]end[/b];
  [b]if[/b] AShortRounding [b]and[/b] (l < High(suffix)) [b]and[/b] (f >= [purple]1000[/purple]) [b]then[/b]
  [b]begin[/b]    [navy][i]// ensures eg. 1022 MB will show 0.99 GB
[/i][/navy]    inc(l);
    f := f / [purple]1024[/purple];
  [b]end[/b];
  Result := Format([teal]'%f %s'[/teal], [f, suffix[l]]);
[b]end[/b];
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top