[Batch] Script to obtain and check the REAL PHYSICAL RAM installed .

Discussion in 'Scripting' started by Claysoft65, Apr 28, 2011.

  1. Claysoft65

    Claysoft65 MDL Member

    Sep 4, 2009
    136
    51
    10
    #1 Claysoft65, Apr 28, 2011
    Last edited by a moderator: Apr 20, 2017
    [Batch] Script to obtain and check the REAL PHYSICAL RAM installed .

    Hi guys
    Some days ago I started thinking to realize a little app to Patch the Kernel in x86 Win 7 for PC with more than 4 GB RAM.
    The only scripting language that I know fairly well and that i thought it could be "simple" for a thing like that is Batch,
    so i started to search for what I needed, first of all for some check to make, possibly, a "Foolproof" mini-patch.
    One of them it's the check for "THE REAL" RAM installed on the MoBo, to exit if PC doesn't have at least 4 GB installed...
    ...well... easy, I thought... Windows is showing it to us (Blue Arrow) just near the RAM that is really available (Green one)...
    [​IMG]
    ...hmmmm... easy ? ...well, yes... and no...
    Yes, if you, after Googling a bit for an already made script, and you wanna use Powershell, C#, or VBscript...
    No, not at all, if you wanna just use a nice and light .CMD file ... now i know why...
    While WMIC store as a single value for the O.S. available RAM (With the WRONG name 'TotalPhysicalMemory', BTW...) there's
    not a single value fo REAL RAM, but only the value of the RAM stored into each single slot of the MoBo.

    I realized, then, that I had a bad idea to do some math calc in CMD, cause I found that it cannot handle numbers greater than
    " 2GB - 1 byte " if you wanna use them with further operations... so you cannot add 'SLOT1 + SLOT2' if result is 2GB or more,
    and if you do 'SLOT1 / 1048576' (for 2, 4 or more GB RAM) cause you think you'll have it in MB, you'll always have 2047 as a
    result, cause the max used value is 2147483647 (2 GB - 1 Byte).[That's why I used MBT=1048575, so the result it's 2048...]

    While realizing how much poor my knowledge was, and after dozens of "Try & Fail", in fight with syntax punctuation, I finally
    had the idea to 'cheat' a bit, and forcedly divide by 10, removing the last char...
    ( I felt, for a moment, like a Brain that defeated a Math Coprocessor... hehehe...)

    As i need to obtain those values using WMIC in a FOR loop, i've been able to handle the problem pretty easily when i was only
    obtaining a single value through WMIC get, like it is into the first 'FOR'...
    On the contrary, working with multiple inputs (like in the second 'FOR'...) I had to do a little bit different approach, and
    a longer fight (lost) with the right syntax so that I could use " :~0,-n% " inside the FOR LOOP...
    One of my "Try & Fail" was pretty absurd for me (even if I was trying it anyway...), cause I really didn't know that I could
    use, inside a FOR Loop, a 'DO Command & CALL :section' pointing to another section of the script...

    Well... it worked, after some more adjustment, so here it is ... :

    Code:
    @echo off
    color 1e
    setlocal enabledelayedexpansion
    SET /A MBT=1024*1024-1
    SET /A MBT1=MBT/10
    
    :phys
    for /f "tokens=2 delims==" %%A in ('wmic computersystem get TotalPhysicalMemory /format:list') do SET MEMPHY=%%A
    
        SET MEMPHY=%MEMPHY:~0,-2%
        SET /A MEMPHYMB=MEMPHY/MBT1
    echo.
    set m
    
    :slot
    for /f "tokens=2 delims==" %%B in ('wmic memorychip get Capacity /format:list') do ( SET MEMSLO=%%B & CALL :calco )
    GOTO :rport
    
    :calco
      SET MEMSLO=%MEMSLO:~0,-3%
      SET /A MEMSLOMB=MEMSLO/MBT1
      SET /A MEMTOTIN=MEMTOTIN+MEMSLOMB
    echo.
    set m
    echo. -----------------------------------
    GOTO :eof
    
    :rport
    echo. -----------------------------------
    set m
    echo. 
    echo. Press any key to show your Installed / Available RAM.
    pause >nul
    
    echo.
    echo. =====================================
    echo.   O.S. Available RAM is :  %MEMPHYMB%  MB.
    echo. =====================================
    echo.
    echo. =====================================
    echo.   REAL Installed RAM is :  %MEMTOTIN%  MB.
    echo. =====================================
    echo.
    
    endlocal & SET MEMTOT=%MEMTOTIN% & SET MEMPHYS=%MEMPHYMB%
    IF %MEMTOT% GEQ 3080 (
      msg %USERNAME% /W  I'll start patching your Kernel, so that you'll be able to use all of your RAM !!
      ) ELSE (
      msg %USERNAME% /W  You have less than 4 GB RAM so this Patch is useless for You... Click OK and Exit !
      )
    set m
    pause >nul
    pause
    The red lines are there just for check, to have a personal output and see if the script was doing what i thought and to have
    the variable progresses for each step.

    The green line could instead be a nice trick, using SETLOCAL/ENDLOCAL to release all the variables of a certain section, but,
    with the rest of the line, saving one or more variables from wiping to reuse them later...(We'll see the effect with last'set')

    I also colored a couple of part in blue, cause i had to play "out-of-the-rules" that i thought should be right, to have the
    ' :~0,-n% ' Parameter working... Just like I said, I had to remove the last one char from the variable obtained from 'WMIC get'
    to simulate a division by 10, so I thought the right syntax shuld have been : ' :~0,-1% ', but it didn't worked, so, after
    some tries, i put a -2 into the first one... bingo !... hhhmmm... no... the second one wasn't working anyway... WTH ?!?
    I had to put a -3 in the Capacity shrinking value to have a single char removed from it...
    I checked so many times that I can't count them, using WMITools all of those value are simple numbers, so no strange char at
    the end, and creating the output of the 'do SET' into a text file there are no further chars at the end (only the CARRIAGE
    RETURN), so, even if the CR was the problem, I could understand why I had to use a -2 ... BUT... WHY -3 for the other one ?!?

    Is there anyone among you that could please enlighten me about it and help me enhance my knowledge ?

    Even if for lots of you there's nothing new here, and even if it's a kind of script that cannot be used so often ( First of all
    because doing it in VBScript or Powershell is surely easier...LOL ) , I thought that it could anyway be an interesting thing
    for 'middle-aged' and 'middle-skilled' scripters (Just like me...), so i decided to post it here at MDL...

    This part of my script has been a huge fight in few moments for me, cause i really couldn't realize WHY certain rules were
    not right like i thought and like i remembered them (my last script 'totally home-made' was...maybe...20-25 years ago...),
    but i surely had fun in doing it, and now that this one is working, i'm sure i'll finish the whole script pretty quick.

    CU All Guys
    Clay

    EDIT : Here it is the updated script after Compo's lessons... :p
    Code:
    @echo off
    color 1e
    SETLOCAL ENABLEEXTENSIONS
    SET /A MBT=1024*1024-1
    SET /A MBT1=MBT/10
    
    :phys
    for /f "tokens=2 delims==" %%A in ('wmic computersystem get TotalPhysicalMemory /VALUE') DO CALL :phystot %%A
    GOTO :slot
    
    :phystot
      SET MEMPHY=%1
      SET/A MEMPHYMB=%MEMPHY:~0,-1%/MBT1
    GOTO :eof
    
    :slot
    for /f "tokens=2 delims==" %%A in ('wmic memorychip get Capacity /VALUE') DO CALL :slotot %%A
    GOTO :rport
    
    :slotot
      SET MEMSLO=%1
      SET/A MEMSLOMB=%MEMSLO:~0,-1%/MBT1
      SET/A MEMTOTIN=MEMTOTIN+MEMSLOMB
    GOTO :eof
    
    :rport
    echo. 
    echo. ...Here to you the amount of your Installed / Available RAM.
    ping -n 2 127.0.0.1 >NUL
    
    echo.
    echo. =====================================
    echo.   O.S. Available RAM is :  %MEMPHYMB%  MB.
    echo. =====================================
    echo.
    echo. =====================================
    echo.   REAL Installed RAM is :  %MEMTOTIN%  MB.
    echo. =====================================
    echo.
    ping -n 4 127.0.0.1 >NUL
    
    rem endlocal & SET MEMTOT=%MEMTOTIN% & SET MEMPHYS=%MEMPHYMB%
    IF %MEMTOTIN% GTR 3072 (
      GOTO :plus4g
      ) ELSE (
      GOTO :noptch
      )
    :plus4g
    SET NFO1=- Test Message - You surely have more
    SET NFO1=%NFO1% than 3 GB RAM !! (will close in 5 seconds)
    GOTO :quest
    :noptch
    SET NFO1=- Test Message - You surely have less
    SET NFO1=%NFO1% than 4 GB RAM !! (will close in 5 seconds)
    GOTO :quest
    
    :quest
    MSG %USERNAME% /TIME:5 /W %NFO1%
    
    ping -n 2 127.0.0.1 >NUL
     
  2. Compo

    Compo MDL Member

    Mar 29, 2011
    136
    106
    10
    #2 Compo, Apr 28, 2011
    Last edited by a moderator: Apr 20, 2017
    That seems like a lot of work to get the Total of RAM, how does this work for you?
    Code:
    @ECHO OFF
    SETLOCAL ENABLEEXTENSIONS
    FOR /F "TOKENS=2 DELIMS==" %%A IN (
    'WMIC MemPhysical GET MaxCapacity /VALUE^|FINDSTR ..*') DO CALL :INTOGIG %%A
    ECHO=TOTAL RAM IS %ALLRAM% GB
    >NUL PING -n 6 127.0.0.1
    GOTO :EOF
    :INTOGIG
    SET/A ALLRAM=%1/1048576
    Bear in mind when using SET with /A that only integers are output
     
  3. Claysoft65

    Claysoft65 MDL Member

    Sep 4, 2009
    136
    51
    10
    #3 Claysoft65, Apr 29, 2011
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Yep... lots of work... and you know why ?... cause EVERYTIME in WMI there's the word "MemPhysical" (or similar, with 'Physical'
    word in it) it's NEVER the REAL mean of Physical... LOL
    I think that the MCI value you used is the MAX SUPPORTED RAM that you can install... on MY PC i'm just Full...
    Max 8 GB ... installed 8 GB, so it looks like i was receiving the right answer...
    Then i checked the script in a VM with 2,25 GB and the script it's giving me 256 GB... :eek:

    MaxCapacity is already giving a value in KB , so there's no need to get mad with it.. the problem is when the value is in Byte...
    BTW... yep, i already knew that SET/A will give me only integer, what i didn't know was that it was limited to 2GB - 1 byte, cause
    i thought it was '4GB - 1 byte'...

    Anyway, that value is useless, and it's a pity, cause it's stored in KB, that was easier to manage in calculation... :biggrin:

    I also tried to use tha value that i found and i tried to modify your script for it, but i'm always receiving the same error that I well
    know when it's finding 2GB or more RAM in a single SLOT... (but maybe you already know that error). :cool:

    Could you please (just to be sure) tell me if I did something wrong while adating your script to the different query ?

    Code:
    @ECHO OFF
    SETLOCAL ENABLEEXTENSIONS
    FOR /F "TOKENS=2 DELIMS==" %%A IN (
    'WMIC memorychip GET Capacity /VALUE^|FINDSTR ..*') DO CALL :INTOMEG %%A
    ECHO=TOTAL RAM IS  %TOTRAM%  MB
    >NUL PING -n 6 127.0.0.1
    GOTO :EOF
    :INTOMEG
    SET/A ALLRAM=%1/1024
    SET/A TOTRAM=TOTRAM+ALLRAM
    On my PC i receive 0 as a result... 4x2GB = 4 errors
    On the VM with 2304 MB RAM i receive 256 MB as a result... error on the first 2 GB "slot".

    Anyway, thanks a lot for your script... I'm pretty sure that if I knew you before, I could have had less headache with this script... :p

    (...but I didn't enjoy so much in finding a solution by myself... :biggrin: ;) )

    CU
    Clay
     
  4. Compo

    Compo MDL Member

    Mar 29, 2011
    136
    106
    10
    #4 Compo, Apr 29, 2011
    Last edited by a moderator: Apr 20, 2017
    I'm not so sure that you are correct, My Motherboard has 4 DIMM slots each supporting 4GB totalling 16GB maximum. I have 2 DIMMS empty and 1 stick of 2GB capacity in each of the other two. My MaxCapacity is returning 4194304 which is correct.

    Yes the fact is that you cannot use a number of that size with SET/A. You best option if you wished to still use the same method is to use a vbscript. If you still prefer to run a batch file you could probably create and run the vbs from it and output the result to your batch file in the same way as you do now.
    Example.cmd:
    Code:
    @ECHO OFF
    SETLOCAL ENABLEEXTENSIONS
    (SET TMP_=%TEMP%\_$.VBS)
    >"%TMP_%" FINDSTR/E 'VBS "%~f0"
    FOR /F %%A IN ('CSCRIPT //NOLOGO "%TMP_%"') DO (SET RAMTOT=%%A)
    DEL "%TMP_%"
    IF %RAMTOT% GTR 3072 (GOTO PATCHIT)
    ECHO=You do not have more than 3 GB RAM so this Patch is useless for you...^
     Press any key to Exit.
    PAUSE>NUL
    GOTO :EOF
    :PATCHIT
    (SET NFO=I'll start patching your Kernel,)
    (SET NFO=%NFO% so that you'll be able to use all of your RAM !!)
    MSG %USERNAME% /W %NFO%
    PAUSE
    GOTO :EOF
    REM ===========================================================================
    Set obj = GetObject("winmgmts:").InstancesOf("Win32_PhysicalMemory") 'VBS
    i = 1 'VBS
    For Each obj2 In obj 'VBS
    memTmp1 = obj2.capacity / 1048576 'VBS
    TotalRam = TotalRam + memTmp1 'VBS
    i = i +1 'VBS
    Next 'VBS
    WScript.echo TotalRam 'VBS
    
    You can obviously edit the text etc. as you wish.
    Please make sure that you do not remove the blank line at the bottom of the script
     
  5. Claysoft65

    Claysoft65 MDL Member

    Sep 4, 2009
    136
    51
    10
    #5 Claysoft65, Apr 29, 2011
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Yep... I'm sure you're right... Looking better at them with WMITools Object Browser I saw that memorychip is a sub-class of MemPhysical,
    so the value that you told me is surely right. When I saw that value in my VM, I did the error to not "double-check" in WMITool both
    VM and my PC and (I really don't know why...) as into the VMPlayer VM that value is 256 GB and do not change if you change the
    Virtual RAM assigned to the VM, i assumed that it was something like a MaxSupportedInstalledRAM.
    I also re-checked my MoBo website and i saw that a 1 year old BIOS has updated my MoBo and i could install 16 GB RAM too and that's
    why my manual was still reporting 8 GB as the Max... o_O
    So, even checking my real PC, i would have thought that the obtained value wasn't my REAL Installed RAM...
    And i surely would never try to remove some RAM to check... LOL

    Thanks for your advice, but as i already said in my OP, i already found a ready vbscript for it... maybe it's been just a point of principle,
    but i told to me that i should be able to do it only with Batch.. :p

    BTW... still talking about 'SET'...
    Are you maybe able to understand and explain to me why this ABSURD behaviour for the ' :~0,n% ' Parameter ?!?

    Thx again for your help
    Clay

    EDIT : I was already writing my post when you added the script example... LOL
    My limited skill is allowing me to understand it, but i surely would never been able to write it by myself... :worthy:
    The use of 'FINDSTR/E' in that way is amazing . Is there any real difference versus the 'classic' way that i use (if needed...) ? :

    Code:
    SET TMP_="%~dp0MY.VBS"
    echo Set obj = GetObject("winmgmts:").InstancesOf("Win32_PhysicalMemory")>%TMP_%
    echo For Each obj2 In obj>>%TMP_%
    ...and so on...
    I'm still pretty sure that i'll go for a cmd script with no vbs (VBscripting is one of the first thing that i disable, so i'd like to have it
    working even in a PC that has VBS disable too...:p) , but surely your VBS is welcome... :worthy:
    The VBScript is (more or less...) what i already found... yours is not using ' & strComputer & "\root\cimv2" ' but i think that they
    are the default values used if nothing is specified, so there shouldn't be the need for them...
    ...juust a question (sorry to bother you with another one...:cool:) ... what's the use of that counter ( i = 1 ) ?!?
    For...Next is not enough to realize that Loop ? Am I wrong ?

    CU
    Clay
     
  6. Compo

    Compo MDL Member

    Mar 29, 2011
    136
    106
    10
    #6 Compo, Apr 29, 2011
    Last edited by a moderator: Apr 20, 2017
    The reason for your blue colored problems is that the output from WMIC has a nasty hidden character at the end of it. Try this one liner directly in a console window to see what I mean:
    Code:
    FOR /F "TOKENS=2 DELIMS==" %A IN ('WMIC memorychip GET Capacity /VALUE^|FINDSTR ..*') DO @ECHO [%A]
    The hidden character causes all sorts of problems which is why in my example I remove it as if by magic by sending it as a parameter with the call function.

    The biggest problem with writing your vbs line by line with echo is that there are often occasions where characters need echoing which are problems to cmd; (they would need escaping).

    Finally yes, I was a little lazy after playing with some stuff in the vbscript and could have left out both of the count related lines, i=
     
  7. Claysoft65

    Claysoft65 MDL Member

    Sep 4, 2009
    136
    51
    10
    #7 Claysoft65, Apr 30, 2011
    Last edited by a moderator: Apr 20, 2017
    (OP)
    LOL... WTH of output is that ??
    Code:
    ]2147483648
    ]2147483648
    ]2147483648
    ]2147483648
    So, after all your teaching :biggrin: I think that my code will be changed on something like that :
    (this is just the code i wrote down to see a good output using your 'DO CALL' trick... thx again, dude...)
    Code:
    @echo off
    FOR /F "TOKENS=2 DELIMS==" %%A IN ('WMIC memorychip GET Capacity /VALUE') DO CALL :INTRO %%A
    echo.
    FOR /F "TOKENS=2 DELIMS==" %%A IN ('wmic computersystem get TotalPhysicalMemory /VALUE') DO CALL :INTRO2 %%A
    echo.
    pause
    
    :INTRO
    echo.
    ECHO [%1]
    SET SLO=%1
    SET/A SLO=%SLO:~0,-1%/104857
    echo -%SLO%- .MB.
    SET/A SLO1=SLO1+SLO
    GOTO :eof
    
    :INTRO2
    echo.
    ECHO [%1]
    SET SLO2=%1
    SET/A SLO2=%SLO2:~0,-1%/104857
    echo.
    echo -%SLO2%- .MB. Available.
    echo.
    echo -%SLO1%- .MB. Installed.
    (...and the ':~0,-1%' is working now like it should be... DAMN M$... they cannot even handle an output from their own stuff... :mad: )
    Let's see on the next teaching lesson... :p
    CU
    Clay
     
  8. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    You guy's got some good scripting going on here ;)
     
  9. Compo

    Compo MDL Member

    Mar 29, 2011
    136
    106
    10
    #9 Compo, Apr 30, 2011
    Last edited by a moderator: Apr 20, 2017
    Just a quick update on the example code you posted in your last message. There was an error in it, you needed a GOTO :EOF before your subroutines began, (otherwise the script would continue and run the subroutines again as part of the linear read of the file).

    The other thing I''ll mention, (personal preference only), is that you leave the subroutines when you no longer need to be in them, once the values have been created you can echo the information within the main body of the script.
    Code:
    @ECHO OFF
    SETLOCAL
    FOR /F "TOKENS=2 DELIMS==" %%A IN (
    'WMIC MemoryChip GET Capacity /VALUE') DO CALL :BANKS %%A
    ECHO=
    ECHO=-%SLO1%- .MB. Installed
    FOR /F "TOKENS=2 DELIMS==" %%A IN (
    'WMIC ComputerSystem GET TotalPhysicalMemory /VALUE') DO (
    CALL :TOTAL %%A
    )
    ECHO=
    ECHO=-%SLO2%- .MB. Available.
    ECHO=
    PAUSE
    GOTO :EOF
    
    :BANKS
    SET SLO=%1
    SET/A SLO=%SLO:~,-1%/104857
    SET/A SLO1+=SLO
    GOTO :EOF
    
    :TOTAL
    SET SLO2=%1
    SET/A SLO2=%SLO2:~,-1%/104857
     
  10. Claysoft65

    Claysoft65 MDL Member

    Sep 4, 2009
    136
    51
    10
    #10 Claysoft65, Apr 30, 2011
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Yep, I agree with you... it was just too fast in modern PC to let us see that my :INTRO subroutine was reapeted after the pause before exit... :p
    But it was also a fast example that I made to be sure that using that trick the '~0,-1' was working and i didn't "double-check" if the Loop was
    already completed or not... hehehe... i'm lazy too :p
    (... and you can easily see, in the updatad script that i added in the OP, that i didn't made the same error... :biggrin: )

    About your "personal preference", I think that it's surely the best thing to do when working with 'CALL :subroutine' even if it's usually hard, for
    me, to mantain the whole 'body of the script' intact, while moving all subroutine at the end of the script (personal preference...too), but, apart
    from that, I totally agree that a subroutine has always to start with a :caption and end with a GOTO, to be sure that you're not going
    to fall into an endless Loop...
    Just to make a corrected example of what i mean, based on my 'wrong-but-too-fast-to-be-visible' :biggrin: previous script... :
    Code:
    @echo off
    FOR /F "TOKENS=2 DELIMS==" %%A IN ('WMIC memorychip GET Capacity /VALUE') DO CALL :INTRO %%A
    echo.
    FOR /F "TOKENS=2 DELIMS==" %%A IN ('wmic computersystem get TotalPhysicalMemory /VALUE') DO CALL :INTRO2 %%A
    echo.
    GOTO :show
    
    :INTRO
    echo.
    SET SLO=%1
    SET/A SLO=%SLO:~0,-1%/104857
    SET/A SLO1=SLO1+SLO
    GOTO :eof
    
    :INTRO2
    echo.
    SET SLO2=%1
    SET/A SLO2=%SLO2:~0,-1%/104857
    GOTO :eof
    
    :show
    echo.
    echo -%SLO2%- .MB. Available.
    echo.
    echo -%SLO1%- .MB. Installed.
    echo.
    pause
    I often use this kind of 'construction' for subroutine that I have to use for a single Loop, maybe, so that it's easier to check them in debug moments,
    writing them near the CALL for them, without having to scroll down the page if you're doing a large script...
    On the contrary, when I use subroutines that could be CALLed for more times during the execution, i'm used to put all of them at the End of
    the script, cause in that case too, it's easier to go to check-control one of them starting from any part of the script.
    Again looking at my updated script in the OP, you can see that i also use quite often some 'useless' caption, that i anyway think that could
    be a better 'self-explaining' way to see how the script is going on without using those boring REM lines, if, just like me, you're used to continue
    to work to a script maybe some months after your last edit of it...
    ...as we both already said... they're a lot of 'personal preference' and most of them won't fit for other ppl...

    I hoe that what ppl is writing here, in this kind of sections of MDL forum, could be useful for more ppl than just me. :p

    CU Later, guys
    Clay