#201809 - 2011-03-29 03:48 PM
Problems with Memory() UDF and Windows 7 x64
|
Allen
KiX Supporter
Registered: 2003-04-19
Posts: 4549
Loc: USA
|
Hey Glenn. I'm having issues with the Memory() UDF on Win7 x64. It reports 3346 on a system that has 8gb of ram.
Here is my .translated value.
010000000000000000000000000000000300000003010000001000000000000000e00900000000000301000000001000000000000000e8cf000000000701000200000000010000000000300100000000
Any ideas?
|
Top
|
|
|
|
#201816 - 2011-03-30 02:53 AM
Re: Problems with Memory() UDF and Windows 7 x64
[Re: Glenn Barnas]
|
Allen
KiX Supporter
Registered: 2003-04-19
Posts: 4549
Loc: USA
|
Looking at that code would certainly deserve your response.
I had a old script that had the got the memory slot info, and I added the memory info to it tonight... so for me there is no hurry now. Thanks though.
GetMemoryInfo() - Get Information Related to the Memory and Slots on a PC
|
Top
|
|
|
|
#207990 - 2013-11-03 02:40 PM
Re: Problems with Memory() UDF and Windows 7 x64
[Re: Glenn Barnas]
|
Glenn Barnas
KiX Supporter
Registered: 2003-01-28
Posts: 4396
Loc: New Jersey
|
OK - I think I've got it!
I've tested the new code on Windows 7 (x86/64), Windows 8 (x86/64), Server 2003 (x86), Server 2008 (x64), and Server 2012 (x64) with accurate results. Memory sizes ranged from 2GB to 12GB. I also tested by injecting your .Translated value and got 8153MB - about 40MB off from the physical 8192MB. This is usually a memory or BIOS window.
Here's the code to test with:Break On
$Mem = Memory() ; get RAM size from local computer
$MSize = 512 ; Smallest RAM module in service
$Ma = $Mem / $MSize ; Divide by smallest module size
If $Mem Mod $MSize $Ma = $Ma + 1 EndIf ; If a fractional module is detected, add another full module
$Ma = $Ma * $MSize ; calc installed RAM by multiplying modules * ModuleSize
' Reported: ' $Mem ?
' Adjusted: ' $Ma ?
'Difference: ' $Ma - $Mem ?
' Gigabytes: ' $Ma / 1024 ? and here's the updated UDF;;FUNCTION Memory()
;;
;;AUTHOR Glenn Barnas
;;
;;ACTION Returns the amount of Available Physical RAM in a local or remote system
;;
;;SYNTAX Memory([system])
;;
;;VERSION 4.0
;;
;;DATE v1.0 - 2004/02/04
;;
;;DATE REVISED v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;; v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;; v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
;;
;;PARAMETERS System - OPTIONAL - name of system to query. Default is local system
;;
;;REMARKS Returns Physical RAM size available to the O/S using registry memory allocation map
;; Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;; DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache
;; or video adapters and this memory is not reported. This can be adjusted for using
;; the second example below.
;;
;;RETURNS Integer - Available Physical RAM (in Megabytes)
;;
;;DEPENDENCIES None
;;
;;TESTED WITH WinXP, Vista, Win7, Win8
;; Windows Server 2000, 2003, 2008, 2012
;; Tested with up to 16G of RAM
;;
;;EXAMPLES $RAM = Memory('ThatPC') ; Get the available RAM from a remote computer
;;
;; ; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;; ; deployed DIMM module as an increment. Use "1024" for full GB increments.
;; ; If the GB flag is used, this method must be adjusted to define MSize in GB values
;; ; (e.g. 0.5 instead of 512).
;; $MSize = 512 ; Size of smallest RAM module (DIMM)
;;
;; $Mem = Memory() ; get reported memory
;; $Ma = $Mem / $MSize ; determine number of modules installed
;;
;; ; If a fractional module is detected, add another full module
;; ; this accounts for a fractional module used for BIOS cache or video RAM
;; If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;;
;; ; $Mem now holds a value based more closely on installer rather than available RAM
;; $Mem = $Ma * $MSize ; Memory is #_modules * Mod_Size
;;
;;
;
Function Memory(Optional $_System, Optional $_fGB)
Dim $_MemMap ; Physical Memory Map
Dim $_Start, $_End, $_Step ; for/next start & step increment
Dim $_Sum ; running sum of memory from map
Dim $_Idx ; temporary index var
Dim $_iMem ; Memory region size index
Dim $_Error ; Error placeholder
; Insure $_System has "\\System\" format if it is specified
If $_System <> ''
$_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
EndIf
; Get the memory value from the registry
$_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
$_MemMap = ReadValue($_Idx, '.Translated')
; Check for invalid read and Return
If Len($_MemMap) = 0 Or @ERROR
$Memory = 0 ; return 0 Mbytes
$_Error = IIf(@ERROR, @ERROR, 13) ; Return "Data is Invalid" if no error but data is blank
Exit $_Error
EndIf
; determine system's O/S type based on architecture
$_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
$_Step = 40 ; Define the step size based on the O/S Architecture
$_Start = 33 ; Offset where memory descriptor blocks start
$_Sum = 0.0 ; no unreported base memory to account for
$_iMem = 10 ; Memory size index
Else
$_Step = 32 ; Define the step size based on the O/S Architecture
$_Start = 41 ; Offset where memory descriptor blocks start
$_Sum = 737280.0 ; account for base memory not identified in memory map - x86 only
$_iMem = 2 ; Memory size index
EndIf
$_End = Len($_MemMap) - 8
For $_Idx = $_Start to $_End Step $_Step
$_Block = SubStr($_MemMap, $_Idx, $_Step)
If SubStr($_Block, $_iMem, 1) > 3
$_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
Else
$_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
+ CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
EndIf
Next
; Sum is in Bytes - return the total as megabytes
$Memory = CInt($_Sum / 1048576)
Exit 0
EndFunction Let me know if this works for you. I still need to test some older platforms, particularly Server 2003 or XP 64-bit systems. Not sure if I should worry about older platforms than that..
Glenn
_________________________
Actually I am a Rocket Scientist!
|
Top
|
|
|
|
#208003 - 2013-11-05 06:01 PM
Re: Problems with Memory() UDF and Windows 7 x64
[Re: Glenn Barnas]
|
Allen
KiX Supporter
Registered: 2003-04-19
Posts: 4549
Loc: USA
|
Server 2012 R2 with 16GB reports 16339.
My Win 8 x64 with 8GB now reports 8153.
Mucho better
|
Top
|
|
|
|
Moderator: Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart
|
0 registered
and 351 anonymous users online.
|
|
|