How do I get total physical memory size using PowerShell without WMI?
Asked Answered
F

15

28

I'm trying to get the physical memory size using PowerShell, but without using get-wmiobject.

I have been using the following PS cmdlet to get the physical memory size, but the value changes with each new poll.

(get-counter -counter "\Memory\Available Bytes").CounterSamples[0].CookedValue + 
(get-counter -counter "\Memory\Committed Bytes").CounterSamples[0].CookedValue

In general, this gives me a value around: 8605425664 bytes

I'm also testing the value I get from adding these counters with the returned value from

(get-wmiobject -class "win32_physicalmemory" -namespace "root\CIMV2").Capacity

This gives me the value: 8589934592 bytes

So, not only is the total physical memory calculated from counters changing, but it's value differs from the WMI value by a couple megabytes. Anyone have any ideas as to how to get the physical memory size without using WMI?

Fleshings answered 16/7, 2013 at 15:50 Comment(2)
Just out of curiosity, why do you want to avoid WMI?Patrology
I'm avoiding WMI because it requires DCOM permissions, so a user without permissions wouldn't be able to get this information.Fleshings
C
34

If you don't want to use WMI, I can suggest systeminfo.exe. But, there may be a better way to do that.

(systeminfo | Select-String 'Total Physical Memory:').ToString().Split(':')[1].Trim()
Cadal answered 16/7, 2013 at 16:11 Comment(7)
Interesting, on my system which has 8GB installed (or exactly 8192MB), system info reports that I have a total of 8155MB. I suspect that not all of the 8GB is usable by the system which could account for the difference.Patrology
Yes. Your BIOS may be mapping certain amount of memory for BIOS shadowing functions.Cadal
So the question is - what is the OP actually after? Installed memory or total memory available for use by the computer?Patrology
I guess installed memory. Using systeminfo.exe, you cannot actually get the accurate value but that is the only option without WMI, AFAIK.Cadal
Yes. I'm looking for installed memory. Thank you ravikanth.Fleshings
+1 Slight caveat: does not work on non-english OS, because the output is localized. But that's easy to fix, alternatively (systeminfo | Select-String ' MB')[0] did the trick for me.Shame
Another Way using syteminfo with the format CSV option and converting to a structured powershell object to get the value systeminfo /FO CSV | ConvertFrom-CSV | select "Total Physical Memory"Java
T
39

Let's not over complicate things...:

(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb
Technocracy answered 21/2, 2019 at 15:29 Comment(0)
C
34

If you don't want to use WMI, I can suggest systeminfo.exe. But, there may be a better way to do that.

(systeminfo | Select-String 'Total Physical Memory:').ToString().Split(':')[1].Trim()
Cadal answered 16/7, 2013 at 16:11 Comment(7)
Interesting, on my system which has 8GB installed (or exactly 8192MB), system info reports that I have a total of 8155MB. I suspect that not all of the 8GB is usable by the system which could account for the difference.Patrology
Yes. Your BIOS may be mapping certain amount of memory for BIOS shadowing functions.Cadal
So the question is - what is the OP actually after? Installed memory or total memory available for use by the computer?Patrology
I guess installed memory. Using systeminfo.exe, you cannot actually get the accurate value but that is the only option without WMI, AFAIK.Cadal
Yes. I'm looking for installed memory. Thank you ravikanth.Fleshings
+1 Slight caveat: does not work on non-english OS, because the output is localized. But that's easy to fix, alternatively (systeminfo | Select-String ' MB')[0] did the trick for me.Shame
Another Way using syteminfo with the format CSV option and converting to a structured powershell object to get the value systeminfo /FO CSV | ConvertFrom-CSV | select "Total Physical Memory"Java
F
22

I'd like to make a note of this for people referencing in the future.

I wanted to avoid WMI because it uses a DCOM protocol, requiring the remote computer to have the necessary permissions, which could only be setup manually on that remote computer.

So, I wanted to avoid using WMI, but using get-counter often times didn't have the performance counter I wanted.

The solution I used was the Common Information Model (CIM). Unlike WMI, CIM doesn't use DCOM by default. Instead of returning WMI objects, CIM cmdlets return PowerShell objects.

CIM uses the Ws-MAN protocol by default, but it only works with computers that have access to Ws-Man 3.0 or later. So, earlier versions of PowerShell wouldn't be able to issue CIM cmdlets.

The cmdlet I ended up using to get total physical memory size was:

get-ciminstance -class "cim_physicalmemory" | % {$_.Capacity}
Fleshings answered 17/7, 2013 at 16:52 Comment(2)
If the machine has multiple RAM banks installed, your command will return a list. The following one will show a total: (Get-CimInstance -ClassName 'Cim_PhysicalMemory' | Measure-Object -Property Capacity -Sum).SumCagey
I replaced Get-CimInstance with Get-WmiObject for good measureLeontine
M
10

Id like to say that instead of going with the systeminfo this would help over to get the total physical memory in GB's the machine

Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}

you can pass this value to the variable and get the gross output for the total physical memory in the machine

   $totalmemory = Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | Foreach {"{0:N2}" -f ([math]::round(($_.Sum / 1GB),2))}
   $totalmemory
Mislay answered 3/8, 2016 at 17:34 Comment(0)
D
3

For those coming here from a later day and age and one a working solution:

(Get-WmiObject -class "cim_physicalmemory" | Measure-Object -Property Capacity -Sum).Sum

this will give the total sum of bytes.

$bytes = (Get-WmiObject -class "cim_physicalmemory" | Measure-Object -Property Capacity -Sum).Sum

$kb = $bytes / 1024
$mb = $bytes / 1024 / 1024
$gb = $bytes / 1024 / 1024 / 1024

I tested this up to windows server 2008 (winver 6.0) even there this command seems to work

Delagarza answered 1/9, 2017 at 8:38 Comment(1)
I prefer to use the built in size constants to convert bytes to MB, KB and GB. $kb = $bytes / 1KB $mb = $bytes / 1MB $gb = $bytes / 1GB learn.microsoft.com/en-us/previous-versions/windows/it-pro/…Mainly
F
3

This gives you the total amount from another WMI class:

$cs = get-wmiobject -class "Win32_ComputerSystem"
$Mem = [math]::Ceiling($cs.TotalPhysicalMemory / 1024 / 1024 / 1024)

Hope this helps.

Featherhead answered 6/11, 2018 at 11:49 Comment(0)
T
1

Using Get-CimInstance gives you the individual sizes of each RAM stick which you have to manually add up. Thus I prefer Get-WMIObject when possible:

(Get-WMIObject Win32_OperatingSystem).TotalVisibleMemorySize  # in KB

38326300
(Get-WMIObject Win32_OperatingSystem).TotalVisibleMemorySize / 1MB  # in GB

31.8008079528809
Tempestuous answered 17/6, 2021 at 14:2 Comment(0)
T
1
 Get-ComputerInfo | select -Property OsTotalVisibleMemorySize
Tanana answered 28/8, 2022 at 14:50 Comment(0)
B
0

Maybe not the best solution, but it worked for me.

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
$VBObject=[Microsoft.VisualBasic.Devices.ComputerInfo]::new()
$SystemMemory=$VBObject.TotalPhysicalMemory
Bander answered 31/5, 2018 at 15:42 Comment(0)
M
0

Below gives the total physical memory.

gwmi Win32_OperatingSystem | Measure-Object -Property TotalVisibleMemorySize -Sum | % {[Math]::Round($_.sum/1024/1024)}
Mesa answered 11/10, 2019 at 6:12 Comment(0)
B
0

This is not my creation but I found this and it displays the data beautifully in a human-readable format.

[Cmdletbinding()] 
Param( 
    [string]$Computername = "."
) 
cls 
$PysicalMemory = Get-WmiObject -class "win32_physicalmemory" -namespace "root\CIMV2" -ComputerName $Computername 
 
Write-Host "Memore Modules:" -ForegroundColor Green 
$PysicalMemory | Format-Table Tag,BankLabel,@{n="Capacity(GB)";e={$_.Capacity/1GB}},Manufacturer,PartNumber,Speed -AutoSize 
 
Write-Host "Total Memory:" -ForegroundColor Green 
Write-Host "$((($PysicalMemory).Capacity | Measure-Object -Sum).Sum/1GB)GB" 
 
$TotalSlots = ((Get-WmiObject -Class "win32_PhysicalMemoryArray" -namespace "root\CIMV2" -ComputerName $Computername).MemoryDevices | Measure-Object -Sum).Sum 
Write-Host "`nTotal Memory Slots:" -ForegroundColor Green 
Write-Host $TotalSlots 
 
$UsedSlots = (($PysicalMemory) | Measure-Object).Count  
Write-Host "`nUsed Memory Slots:" -ForegroundColor Green 
Write-Host $UsedSlots 
 
If($UsedSlots -eq $TotalSlots)
{ 
    Write-Host "All memory slots are in use. No available slots!" -ForegroundColor Yellow 
} 

Powershell ISE Screenshot

Bawdy answered 22/9, 2021 at 18:50 Comment(0)
W
0

Tested and win32_computerSystem(cim_computerSystem) and win32_operatingSystem(cim_operatingSystem) both work when remotely querying virtual machines. The other options give fake results.

Wordsworth answered 27/7, 2022 at 8:27 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Colcothar
N
0

There's lots of interesting answers here. On review I came up with:

(Get-CimInstance -ClassName "cim_physicalmemory").Capacity/1gb

Principally, it can be converted simply by selecting the required scalar value, i.e. 1kb, 1mb, 1pb or 1eb

Noonberg answered 10/3, 2023 at 9:6 Comment(0)
T
0

While querying memory across all our servers I found that the currently most upvoted answer

(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb

did not always give accurate results. e.g. it reported a server with 1.7GB of memory as having 0.5GB.

I found the following method to be more reliable:

[Math]::Round((Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory / 1GB, 2)
Trull answered 29/2, 2024 at 0:5 Comment(0)
K
0

I found my way here in 2024 looking for a (somewhat) platform-agnostic solution.

I needed something that would work on both Windows & Linux, and I needed it to always give me the same object 'type'/'shape'. Obviously WMI isn't an option, and I probably wouldn't use it even if it was.

For anyone else looking for something similar, I threw together this quick function. It uses free on Linux and systeminfo on Windows, as suggested elsewhere in this thread.

I doubt it will work on anything other than Windows/Linux, although you're welcome to try.

function Get-AvailableMemory
{
    [CmdletBinding()]
    param()

    $Script:PSNativeCommandUseErrorActionPreference = $true

    $spaceUnit = New-Object PSObject -Property ([ordered]@{
            'Bytes' = [ulong]0
    }) | 
        Add-Member -MemberType ScriptProperty -Name 'Kibibytes' -Value { [double]($this.Bytes / 1Kb) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1Kb) } -Force -PassThru  | 
        Add-Member -MemberType ScriptProperty -Name 'Kilobytes' -Value { [double]($this.Bytes / 1000) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1000) } -Force -PassThru | 
        Add-Member -MemberType ScriptProperty -Name 'Mebibytes' -Value { [double]($this.Bytes / 1Mb) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1Mb) } -Force -PassThru |
        Add-Member -MemberType ScriptProperty -Name 'Megabytes' -Value { [double]($this.Bytes / 1000000) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1000000) } -Force -PassThru |
        Add-Member -MemberType ScriptProperty -Name 'Gibibytes' -Value { [double]($this.Bytes / 1Gb) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1Gb) } -Force -PassThru |
        Add-Member -MemberType ScriptProperty -Name 'Gigabytes' -Value { [double]($this.Bytes / 1000000000) } -SecondValue { $this.Bytes = [ulong]($args[0] * 1000000000) } -Force -PassThru |
        Add-Member -MemberType ScriptMethod -Name 'ToString' -Value { $this.Mebibytes.ToString('0,0 "MiB"') } -Force -PassThru

    $result = New-Object PSObject -Property ([ordered]@{
            'Physical' = New-Object PSObject -Property ([ordered]@{
                    'Total' = $spaceUnit.PSObject.Copy()
                    'Used'  = $spaceUnit.PSObject.Copy()
                    'Free'  = $spaceUnit.PSObject.Copy()
                }) | Add-Member -MemberType ScriptMethod -Name 'ToString' -Value { ('{0}/{1} MiB' -f $this.Free.Mebibytes.ToString('0,0'), $this.Total.Mebibytes.ToString('0,0')) } -Force -PassThru
            'Virtual'  = New-Object PSObject -Property ([ordered]@{
                    'Total' = $spaceUnit.PSObject.Copy()
                    'Used'  = $spaceUnit.PSObject.Copy()
                    'Free'  = $spaceUnit.PSObject.Copy()
                }) | Add-Member -MemberType ScriptMethod -Name 'ToString' -Value { ('{0}/{1} MiB' -f $this.Free.Mebibytes.ToString('0,0'), $this.Total.Mebibytes.ToString('0,0')) } -Force -PassThru
        })

    if ($Global:IsLinux)
    {
        $free = ((Invoke-Expression 'free -b') -replace '^\w+:') -replace '[\s\t]+', ',' | ConvertFrom-Csv -WarningAction SilentlyContinue
        $result.Physical.Total.Bytes = [ulong]::Parse($free[0].total)
        $result.Physical.Used.Bytes = [ulong]::Parse($free[0].used)
        $result.Physical.Free.Bytes = [ulong]::Parse($free[0].free)
        $result.Virtual.Total.Bytes = [ulong]::Parse($free[1].total)
        $result.Virtual.Used.Bytes = [ulong]::Parse($free[1].used)
        $result.Virtual.Free.Bytes = [ulong]::Parse($free[1].free)
    }
    elseif ($Global:IsWindows)
    {
        if (!(Test-Path 'C:\windows\system32\systeminfo.exe'))
        {
            throw New-Object System.NotSupportedException("systeminfo.exe couldn't be found")
        }

        # The redirection prevents systeminfo writing its current status to the error stream. You can remove it if you'd rather.
        $infoRaw = Invoke-Expression 'systeminfo.exe /FO CSV 2> $null'
        $info = $infoRaw[-1] | ConvertFrom-Csv -Header ($infoRaw[0] -replace '[\s:]').Split(',', [System.StringSplitOptions]::RemoveEmptyEntries -bor [System.StringSplitOptions]::TrimEntries).Trim('"')
        $numberFormat = New-Object System.Globalization.NumberFormatInfo -Property @{'CurrencySymbol' = 'MB'}
        $numberStyle = [System.Globalization.NumberStyles]::Currency
        $result.Physical.Total.Mebibytes = [int]::Parse($info.TotalPhysicalMemory, $numberStyle, $numberFormat)
        $result.Physical.Used.Mebibytes = ([int]::Parse($info.TotalPhysicalMemory, $numberStyle, $numberFormat) - [int]::Parse($info.AvailablePhysicalMemory, $numberStyle, $numberFormat))
        $result.Physical.Free.Mebibytes = [int]::Parse($info.AvailablePhysicalMemory, $numberStyle, $numberFormat)
        $result.Virtual.Total.Mebibytes = [int]::Parse($info.VirtualMemoryMaxSize, $numberStyle, $numberFormat)
        $result.Virtual.Used.Mebibytes = [int]::Parse($info.VirtualMemoryInUse, $numberStyle, $numberFormat)
        $result.Virtual.Free.Mebibytes = [int]::Parse($info.VirtualMemoryAvailable, $numberStyle, $numberFormat)
    }
    else
    {
        throw New-Object System.NotSupportedException('This command only supports Windows and Linux')
    }

    return $result
}
Kersten answered 1/8, 2024 at 16:41 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.