trip down Memory Lane

Started by spl, September 04, 2026, 09:43:28 AM

Previous topic - Next topic

spl

Asked for a favor for a WB function to display available memory on a PC. After my initial 'So what?'... they explained reasons. I figured it would be a simple WMI query, but the code below returns 0 whether run in 32 or 64 bit.
;Winbatch 2025 - Available Memory
;it is WMI so should work with earlier versions
strComputer = "."
oWMI = GetObject( "winmgmts:\\" : strComputer : "\root\cimv2")
WQL = "SELECT * FROM  Win32_OperatingSystem" 
oP= oWMI.ExecQuery(WQL)
decimals(2)
ForEach p in oP
  total = p.TotalVisibleMemorySize
  free = p.FreePhysicalMemory
  available = (((total - free) / total) * 100)
  Message("Memory",available)
Next   
oP=0
oWMI=0
Exit

which only returns 0, no errors.

A little perplexed I just ran it as PS code through Std_Out() and get results. I am sure WB can probably do it, just not in a direct way.

;Std_out guess at available memory
;Stan Littlefield 9/2/2026
;========================================================================================================================
Gosub udfs
args = $"$Memory = Get-WmiObject -Class Win32_OperatingSystem
$total = $Memory.TotalVisibleMemorySize
$free = $Memory.FreePhysicalMemory
$available = [Math]::::Round(($total - $free) / $total * 100,2)
$available
$"

cmd="Powershell"
msg='Memory Check'
BoxOpen(msg,cmd:" ":args:@LF:"PLEASE WAIT...MAY TAKE SOME TIME")
TimeDelay(2)
vals = Get_stdout()
BoxShut()
Message("Available Memory %%",vals)
Exit
;======================================================================
:udfs
#DefineSubroutine Get_stdout()
ObjectClrOption("useany","System")
objInfo = ObjectClrNew("System.Diagnostics.ProcessStartInfo")
Output=""
timeOut = ObjectType("I2",5000)
objInfo.FileName = cmd
objInfo.RedirectStandardError = ObjectType("BOOL",@TRUE)
objInfo.RedirectStandardOutput = ObjectType("BOOL",@TRUE)
objInfo.UseShellExecute = ObjectType("BOOL",@FALSE)
objInfo.CreateNoWindow = ObjectType("BOOL",@TRUE)
objInfo.Arguments = args
oProcess = ObjectClrNew("System.Diagnostics.Process")
oProcess.StartInfo = objInfo
oProcess.Start()
oProcess.WaitForExit(timeout)
STDOUT = oProcess.StandardOutput.ReadToEnd()
STDERR = oProcess.StandardError.ReadToEnd()
Output = Output:STDOUT:@CRLF
;If STDERR<>""
;  Output = Output:"STDERR:":STDERR:@CRLF
;Endif
oProcess = 0
objInfo = 0

Return (Output)
#EndSubroutine
Return
;==========================================================
Stan - formerly stanl [ex-Pundit]

JTaylor

You need to force type for the division to show properly.

total = p.TotalVisibleMemorySize + 0.00
free = p.FreePhysicalMemory + 0.00

spl

Thanks Jim. Figured it would be easy, just too lazy to pursue it further. Worth noting that both the updated WB script and the one using Std_out came up with the the same result. Would have assumed calling PS within WB to reduce the percentage significantly. They also asked if WB could call the .NET GC() w/out using PS. I think I remember Tony commenting that the GC() wasn't all that great.
Stan - formerly stanl [ex-Pundit]

td

GC - Garbage Collection?

Another take...

;Winbatch 2025-6 - Available Memory
;it is WMI so should work with earlier versions
strComputer = "."
oWMI = GetObject( "winmgmts:\\" : strComputer : "\root\cimv2")
WQL = "SELECT * FROM  Win32_OperatingSystem" 
oP= oWMI.ExecQuery(WQL)
decimals(2)
ForEach p in oP
  total = p.TotalVisibleMemorySize
  free = ObjectType('r8',p.FreePhysicalMemory) 
  available = ((((total - free)) / total) * 100)
  Message("Memory",available)
Next   
oP=0
oWMI=0
Exit
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

kdmoyers

Tony,  I get Error 3131 not a valid OLE object on line 9.
(winbatch 2026B) (Windows 11)

I guess that is because my WMI is not setup same as yours?

-Kirby
The mind is everything; What you think, you become.

td

Don't know what to tell you. I tried the script above on several systems and it worked as expected. The error suggest that you are getting an empty collection assigned to the oP variable from the WMI query. Are you executing the script as an elevated admin?
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

kdmoyers

It's gotta be me somehow.  I've never been able to get WMI features to work.

<<Are you executing the script as an elevated admin?>>
Well, I run Studio as administrator, and I click the "Run-64bit" button in Studio, so does that mean I run as administrator?  Not sure how that works.

The mind is everything; What you think, you become.

td

We have a collection of Virtual Machines with many of the various out-of-the-box versions of Windows. The script worked on the several I tried.

WinBatch Studio runs with the highest available privilege of the logged on user. The WinBatch install also provides all the WinBatch Studio exes with all the possible manifest combinations in the WinBatch "system" directory.

All that said your elevation status might not be the problem. You could have corrupt or missing .mof files that implement WMI classes. According an AI LLM you can run the following script from a command prompt to compile/recompile your .mof files.

First first run cd C:\Windows\System32\wbem then
for /f %s in ('dir /b *.mof *.mfl') do mofcomp %s
for %i in (*.dll) do regsvr32 -s %i

The best place to start may be to check if the WMI service is even running. Use "services.msc" to check if the "Windows Management Instrumentation" service is in the running state. If it is not, start it.

The above are mostly random ideas with no guarantee that any of it will fix anything.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

spl

Kirby;

Not to make this a contest PS vs WB, as WB has always worked efficiently with WMI. The PS gurus are suggesting CIM over WMI. Below is some PS code you can drop into the PS ISE - it uses CIM. Except for the GC() {Garbage Collection} I dropped it into the Std_Out code and it worked fine in Studio either 32 or 64 bit. What Tony suggested should surely set your WMI straight, but I would be curious if for some reason the PS failed as well.
$pop = New-Object -ComObject wscript.shell
$usedMemory = Get-CimInstance Win32_OperatingSystem
$totalMemory = $usedMemory.TotalVisibleMemorySize
$freeMemory = $usedMemory.FreePhysicalMemory
$availableMemoryPercentage = [Math]::Round(($totalMemory - $freeMemory) / $totalMemory * 100,2)
$pop.Popup("Available Memory Percentage: $availableMemoryPercentage%",4,"Available Memory",4096)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($pop)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Stan - formerly stanl [ex-Pundit]

SMF spam blocked by CleanTalk