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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Physical Memory

Status
Not open for further replies.

EmmaLu

Programmer
Jul 16, 2004
38
US
I would like to determine the physical memory. I have a rountine for an API call using GlobalMemoryStatus() which works only if there is 2GB or less. I understand there is another API call named GlobablMemoryStatusEX(). Can someone give me the Foxpro code to use GlobablMemoryStatusEX() or another way to determine the Physical Memory.

Thanks
 
Hi EmmaLu,

GlobalMemoryStatus() which works only if there is 2GB or less.

Actually, I think it works fine for up to 4 GB memory.

But if you want to use GlobalMemoryStatusEx, it's basically the same structure as GlobalMemoryStatus.

The following is untested, but it should work:

Code:
DECLARE GlobalMemoryStatusEx IN win32API STRING @cMemBuffer
cMemBuffer=REPLICATE(CHR(0),32)
GlobalMemoryStatus(@cMemBuffer)

After the call, bytes 9 - 12 (counting from 1) of cMemBuffer should contain the physical memory in bytes.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
EmmaLu,

On second thoughts ....

I think I was right about the 4 GB limit. With GlobalMemoryStatus(), the physical memory is returned in a 32-bit unsigned integer, which is why I think it can hold 4 GB.

With GlobalMemoryStatusEx, the returned value needs a 64-bit integer. So you would need to take bytes 9 - 16 from the buffer, not 9 - 12 as I first said.

In fact, I just ran my code, and got the correct result from bytes 9 - 12, but I suspect that's only because the computer has less than 4 GB of memory.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Try with WMI
Code:
CLEAR
loCIMV2 = GetObject("winmgmts://localhost/root/cimv2")
GetObject("winmgmts://localhost/root/cimv2")
loProcesses    = loCIMV2.ExecQuery("SELECT * FROM Win32_LogicalMemoryConfiguration")
IF loProcesses.Count > 0
   For Each objProcess in loProcesses
       ? "Total Physical Memory, in bytes: ", TRANSFORM(objProcess.TotalPhysicalMemory)
       ? "Total Virtual Memory, in bytes: ", TRANSFORM(objProcess.TotalVirtualMemory)
       ? "Available Virtual Memory, in bytes: ", TRANSFORM(objProcess.AvailableVirtualMemory)
       ? "Total Page File Space, in bytes: ", TRANSFORM(objProcess.TotalPageFileSpace)
     NEXT
ENDIF
 
Thanks Mike and Zografski. I appreciate your help, but obviously you are both beyond me. I sort of understand what you are saying but neither of the code samples get me all the way there. I have tried to complete the task but can not. Could you please give me the full code.

Below is the code that I was using which does work but won't return more than 2GB:

Code:
DECLARE GlobalMemoryStatus IN Win32API STRING @MemStat
m.stru = long2str(32) + REPLICATE(CHR(0), 28)
=GlobalMemoryStatus(@m.stru)
m._physmemory = str2long(SUBSTR(m.stru, 9, 8))
?'Physical Memory='+ ALLTRIM(STR(m._physmemory))

FUNCTION long2str
   PARAMETERS m.longval
   PRIVATE i, m.retstr
   m.retstr = ""
   FOR i = 24 TO 0 STEP -8
     m.retstr = CHR(INT(m.longval/(2^i))) + m.retstr
     m.longval = MOD(m.longval, (2^i))
   NEXT
RETURN m.retstr
 

EmmaLu,

Sorry, I got it slightly wrong. It's not bytes 9 - 12, it's 9 - 16.

So, take my original code, as follows:

Code:
DECLARE GlobalMemoryStatusEx IN win32API STRING @cMemBuffer
cMemBuffer=REPLICATE(CHR(0),32)
GlobalMemoryStatus(@cMemBuffer)

Then take byes 9 - 16 from cMemBuffer ... SUBSTR(cMemBuffer, 9, 8)

This is the 64-bit integer that you need to convert to a numeric or string value. Your Long2Str does that with 32-bit integers. Off-hand, I can't remember how to do it with 64-bit integers, but it's the same general principle. Perhaps someone else can give you more details.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Is there anyone out there that knows the code to convert the 64bit integer. I have tried but just can't figure this out. (See my code above and the partial answer Mike helped with for details).
Thanks
 
To make it work, you need to set the first 4 Bytes of the buffer to the structure size before using GlobalMemoryStatusEx. And that is 64 (Bytes) for GlobalMemoryStatusEx, not 32 Bytes like for GlobalMemoryStatus.

Code:
DECLARE GlobalMemoryStatusEx IN Win32API STRING @MemStat

Local lcBuffer
lcBuffer = long2str(64) + REPLICATE(CHR(0), 60)
=GlobalMemoryStatusEx(@lcBuffer)
? "total physical ram:", str2dlong(Substr(lcBuffer,9,8))

FUNCTION long2str
   LPARAMETERS tnLongval
   Local lnBit, lcRetStr
   lcRetStr = ""
   FOR lnBit = 24 TO 0 STEP -8
     lcRetStr = CHR(INT(tnLongval/(2^lnBit))) + lcRetStr
     tnLongVal = MOD(tnLongval, (2^lnBit))
   NEXT
RETURN lcRetStr

FUNCTION str2dlong
   LPARAMETERS tcStr
   Local lnPos, lnDLong
   lnDLong = 0
   FOR lnPos = 8 TO 1 STEP -1
       lnDLong = 256*lnDLong + Asc(Substr(tcStr,lnPos,1))
   NEXT
RETURN lnDlong

Theoretical ctobin(substr(m.lcBuffer,9,8),"8RS") would also give the total physical memory. But it returns 0.0000E+0, as there is no bigint type in foxpro.

The str2dlong() function nevertheless should not cause overflow in lnDlong because 2^64 is below the 20 digits N(20) limit of vfp's maximum numeric capability. In my case it returns exactly 2113732608, that is 1.97 GB, which is of course not accurate, but Windows Vista itself does also display only 2016 MB, which is the same, 1.97 GB.

GlobalMemoryStatusEx will also work for >4GB Memory.

Bye, Olaf.
 
Thanks Olaf that is just what I needed.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top