Mega Code Archive

 
Categories / Delphi / System
 

How do I determine the amount of RAM

Title: How do I determine the amount of RAM? 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 // for automatic syntax highlighting see FAQ102-6487: How to include syntax highlighting in code examples. uses Windows; type TMemoryStatusEx = record dwLength: DWORD; dwMemoryLoad: DWORD; ullTotalPhys: Int64; ullAvailPhys: Int64; ullTotalPageFile: Int64; ullAvailPageFile: Int64; ullTotalVirtual: Int64; ullAvailVirtual: Int64; ullAvailExtendedVirtual: Int64; end ; function GetGlobalMemoryRecord: TMemoryStatusEx; type TGlobalMemoryStatusEx = procedure ( var lpBuffer: TMemoryStatusEx); stdcall ; var ms : TMemoryStatus; h : THandle; gms : TGlobalMemoryStatusEx; begin Result.dwLength := SizeOf(Result); h := LoadLibrary(kernel32); try if h 0 then begin @gms := GetProcAddress(h, 'GlobalMemoryStatusEx' ); if @gms nil then gms(Result) else begin 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; end end ; finally FreeLibrary(h); end ; end ; function GetTotalRAM: Int64; begin Result := GetGlobalMemoryRecord.ullTotalPhys; end ; 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 {$SetPEFlags $0020} { /LargeAddressAware } 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 { This function returns a formatted string with at the appropriate level of bytes, kilobytes, megabytes, gigabytes, etc } function FormatBytes(ABytes: Int64; AShortRounding: Boolean = True): String; const suffix : array [ 0..6 ] of String = ( 'B' , 'KB' , 'MB' , 'GB' , 'TB' , 'PB' , 'EB' ); var l : Integer; f : Double; begin l := 0 ; f := ABytes; while (l and (f = 1024 ) do begin inc(l); f := f / 1024 ; end ; if AShortRounding and (l and (f = 1000 ) then begin // ensures eg. 1022 MB will show 0.99 GB inc(l); f := f / 1024 ; end ; Result := Format( '%f %s' , [f, suffix[l]]); end ;