您如何获得计算机的 RAM 总量?

Posted

技术标签:

【中文标题】您如何获得计算机的 RAM 总量?【英文标题】:How do you get total amount of RAM the computer has? 【发布时间】:2010-09-11 10:14:26 【问题描述】:

使用 C#,我想获取我的计算机拥有的 RAM 总量。 使用 PerformanceCounter,我可以通过设置获得可用内存的数量:

counter.CategoryName = "Memory";
counter.Countername = "Available MBytes";

但我似乎无法找到获取内存总量的方法。我该怎么做呢?

更新:

MagicKat:我在搜索时看到了,但它不起作用 - “您是否缺少程序集或引用?”。我希望将其添加到参考文献中,但我没有在那里看到它。

【问题讨论】:

【参考方案1】:

.NET 具有它可以访问的内存量限制。 在 Windows XP 中,2GB 是“硬天花板”。 例如:你可以有 4 GB,当它达到 2 GB 时它会杀死应用程序。

同样在 64 位模式下,您可以在系统外使用一定比例的内存,所以我不确定您是否可以要求全部内容,或者是否有专门的防范措施。

【讨论】:

/否/。总物理内存是指实际安装的实际内存。 其实DevelopingChris是对的。如果您在具有 4 Gig 内存的 XP 机器上调用 GlobalMemoryStatusEx,它将报告仅安装了 3 Gig。 另外,使用 WMI 查询 Win32_ComputerSystem 或 Win32_LogicalMemoryConfiguration 中的 TotalPhysicalMemory 也会产生错误的结果。 谢谢,不是我不明白这个问题,你必须使用不同的来源获取信息而不是 .net 库。 这个答案是唯一有意义的。我现在在使用 VisualBasic 引用的 Win 64 8Gb ram 上厌倦了它。我得到垃圾负值。【参考方案2】:

您可以使用“WMI”。

我找到了一个“sn-p”。

Set objWMIService = GetObject("winmgmts:" _
& "impersonationLevel=impersonate!\\" _ 
& strComputer & "\root\cimv2") 
Set colComputer = objWMIService.ExecQuery _
("Select * from Win32_ComputerSystem")

For Each objComputer in colComputer 
  strMemory = objComputer.TotalPhysicalMemory
Next

【讨论】:

请注意,VB.NET 不再需要Set,这是 VB6 代码吗?【参考方案3】:

var ram = new ManagementObjectSearcher("select * from Win32_PhysicalMemory") .Get().Cast<ManagementObject>().First();

|

var a = Convert.ToInt64(ram["Capacity"]) / 1024 / 1024 / 1024;

(richiede System.Managment.dll 来 riferimento, testato su C# con Framework 4.7.2)

在英国的“a” la ram totale presente 中的questa procedura salva


ulong memory() return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;

|

var b = Convert.ToDecimal(memory()) / 1024 / 1024 / 1024;

(richiede Microsoft.VisualBasics.dll 来自 riferimento, testato su C# Framework 4.7.2)

在 GB effettivamente disponibile 中的 "b" il valore della ram 中的questa procedura salva


【讨论】:

你应该用英文写问题。【参考方案4】:

Windows API函数GlobalMemoryStatusEx可以通过p/invoke调用:

  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  private class MEMORYSTATUSEX
  
     public uint dwLength;
     public uint dwMemoryLoad;
     public ulong ullTotalPhys;
     public ulong ullAvailPhys;
     public ulong ullTotalPageFile;
     public ulong ullAvailPageFile;
     public ulong ullTotalVirtual;
     public ulong ullAvailVirtual;
     public ulong ullAvailExtendedVirtual;
     public MEMORYSTATUSEX()
     
        this.dwLength = (uint)Marshal.SizeOf(typeof(NativeMethods.MEMORYSTATUSEX));
     
  


  [return: MarshalAs(UnmanagedType.Bool)]
  [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);

然后使用like:

ulong installedMemory;
MEMORYSTATUSEX memStatus = new MEMORYSTATUSEX();
if( GlobalMemoryStatusEx( memStatus))
 
   installedMemory = memStatus.ullTotalPhys;

或者您可以使用 WMI(托管但速度较慢)在 Win32_ComputerSystem 类中查询 TotalPhysicalMemory

【讨论】:

这不起作用... long ramuse = (long)stat.TotalPhysical; long ramavailable = (long)stat.AvailablePhysical; long ramtotal = ramavailable + ramuse;整数百分比 = (int)( (float)ramuse / ramtotal * 100);百分比告诉我“70”并且总数在不断变化,给予或接受 100。应该是 72% 代码有效,只是你不需要使用'NativeMethods'来获取对象的大小,你可以这样说:this.dwLength = (uint)Marshal.SizeOf(this);,它的工作原理是一样的(我在使用时遇到了麻烦NativeMethods 所以这个修复现在有效)。 "NativeMethods" 是该类型的命名空间。如果您愿意,可以更改对 SizeOf 的调用。 @Corelgott 无用,因为它放弃了最新信息?我的意思是,每次我查看天气频道时,它都会提供不同的信息,但我不会说它完全没用。我什至不确定如果这个函数每次都没有返回可能不同的信息,你会希望它做什么——它是否应该在第一次调用后“锁定”结果,然后返回陈旧的数据?这在什么方面会更有用? 聚会有点晚了,但我碰巧看到了这个帖子,这个答案不正确。 GlobalMemoryStatusEx 不一定(而且通常不会)给出机器上安装的实际 RAM 量,它给出了操作系统可用的数量,由于驱动程序的保留内存等原因,它几乎总是与安装的数量不同. 要获得安装的实际 RAM 量,您需要调用 GetPhysicallyInstalledSystemMemory 函数,该函数返回正确的总 RAM。 msdn.microsoft.com/en-us/library/windows/desktop/…【参考方案5】:

对于那些使用.net Core 3.0 的人来说,不需要使用PInvoke 平台来获取可用的物理内存。 GC 类添加了一个新方法 GC.GetGCMemoryInfo,它返回一个带有 TotalAvailableMemoryBytes 属性的 GCMemoryInfo Struct。此属性返回垃圾收集器的总可用内存。(与 MEMORYSTATUSEX 值相同)

var gcMemoryInfo = GC.GetGCMemoryInfo();
installedMemory = gcMemoryInfo.TotalAvailableMemoryBytes;
// it will give the size of memory in MB
var physicalMemory = (double) installedMemory / 1048576.0;

【讨论】:

我最喜欢的答案。谢谢。 仅供参考,如果您的应用程序是为 x86 / 32 位进程编译但在 64 位机器上运行,那么这将不会返回安装的真实总系统内存。就我而言,它没有返回 32 GB,而是返回了 2 GB。 @RandyBurden 谢谢你,我会在有时间的时候检查一下,但我想知道如果这是真的,这意味着 API 有问题,怎么会发生这种情况 请注意,您还需要一个“使用系统;”让这段代码工作。【参考方案6】:

兼容 .Net 和 Mono(用 Win10/FreeBSD/CentOS 测试)

ComputerInfo 源代码和PerformanceCounters 用于Mono 并作为.Net 的备份:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;

public class SystemMemoryInfo

    private readonly PerformanceCounter _monoAvailableMemoryCounter;
    private readonly PerformanceCounter _monoTotalMemoryCounter;
    private readonly PerformanceCounter _netAvailableMemoryCounter;

    private ulong _availablePhysicalMemory;
    private ulong _totalPhysicalMemory;

    public SystemMemoryInfo()
    
        try
        
            if (PerformanceCounterCategory.Exists("Mono Memory"))
            
                _monoAvailableMemoryCounter = new PerformanceCounter("Mono Memory", "Available Physical Memory");
                _monoTotalMemoryCounter = new PerformanceCounter("Mono Memory", "Total Physical Memory");
            
            else if (PerformanceCounterCategory.Exists("Memory"))
            
                _netAvailableMemoryCounter = new PerformanceCounter("Memory", "Available Bytes");
            
        
        catch
        
            // ignored
        
    

    public ulong AvailablePhysicalMemory
    
        [SecurityCritical]
        get
        
            Refresh();

            return _availablePhysicalMemory;
        
    

    public ulong TotalPhysicalMemory
    
        [SecurityCritical]
        get
        
            Refresh();

            return _totalPhysicalMemory;
        
    

    [SecurityCritical]
    [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern void GlobalMemoryStatus(ref MEMORYSTATUS lpBuffer);

    [SecurityCritical]
    [DllImport("Kernel32", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);

    [SecurityCritical]
    private void Refresh()
    
        try
        
            if (_monoTotalMemoryCounter != null && _monoAvailableMemoryCounter != null)
            
                _totalPhysicalMemory = (ulong) _monoTotalMemoryCounter.NextValue();
                _availablePhysicalMemory = (ulong) _monoAvailableMemoryCounter.NextValue();
            
            else if (Environment.OSVersion.Version.Major < 5)
            
                var memoryStatus = MEMORYSTATUS.Init();
                GlobalMemoryStatus(ref memoryStatus);

                if (memoryStatus.dwTotalPhys > 0)
                
                    _availablePhysicalMemory = memoryStatus.dwAvailPhys;
                    _totalPhysicalMemory = memoryStatus.dwTotalPhys;
                
                else if (_netAvailableMemoryCounter != null)
                
                    _availablePhysicalMemory = (ulong) _netAvailableMemoryCounter.NextValue();
                
            
            else
            
                var memoryStatusEx = MEMORYSTATUSEX.Init();

                if (GlobalMemoryStatusEx(ref memoryStatusEx))
                
                    _availablePhysicalMemory = memoryStatusEx.ullAvailPhys;
                    _totalPhysicalMemory = memoryStatusEx.ullTotalPhys;
                
                else if (_netAvailableMemoryCounter != null)
                
                    _availablePhysicalMemory = (ulong) _netAvailableMemoryCounter.NextValue();
                
            
        
        catch
        
            // ignored
        
    

    private struct MEMORYSTATUS
    
        private uint dwLength;
        internal uint dwMemoryLoad;
        internal uint dwTotalPhys;
        internal uint dwAvailPhys;
        internal uint dwTotalPageFile;
        internal uint dwAvailPageFile;
        internal uint dwTotalVirtual;
        internal uint dwAvailVirtual;

        public static MEMORYSTATUS Init()
        
            return new MEMORYSTATUS
            
                dwLength = checked((uint) Marshal.SizeOf(typeof(MEMORYSTATUS)))
            ;
        
    

    private struct MEMORYSTATUSEX
    
        private uint dwLength;
        internal uint dwMemoryLoad;
        internal ulong ullTotalPhys;
        internal ulong ullAvailPhys;
        internal ulong ullTotalPageFile;
        internal ulong ullAvailPageFile;
        internal ulong ullTotalVirtual;
        internal ulong ullAvailVirtual;
        internal ulong ullAvailExtendedVirtual;

        public static MEMORYSTATUSEX Init()
        
            return new MEMORYSTATUSEX
            
                dwLength = checked((uint) Marshal.SizeOf(typeof(MEMORYSTATUSEX)))
            ;
        
    

【讨论】:

【参考方案7】:

此功能 (ManagementQuery) 适用于 Windows XP 及更高版本:

private static string ManagementQuery(string query, string parameter, string scope = null) 
    string result = string.Empty;
    var searcher = string.IsNullOrEmpty(scope) ? new ManagementObjectSearcher(query) : new ManagementObjectSearcher(scope, query);
    foreach (var os in searcher.Get()) 
        try 
            result = os[parameter].ToString();
        
        catch 
            //ignore
        

        if (!string.IsNullOrEmpty(result)) 
            break;
        
    

    return result;

用法:

Console.WriteLine(BytesToMb(Convert.ToInt64(ManagementQuery("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem", "TotalPhysicalMemory", "root\\CIMV2"))));

【讨论】:

BytesToMb 函数从何而来? @dlatikay 它的内部函数:private static double BytesToMb(long bytes) return Math.Round(bytes / 1024d / 1024d, 2); 【参考方案8】:
// use `/ 1048576` to get ram in MB
// and `/ (1048576 * 1024)` or `/ 1048576 / 1024` to get ram in GB
private static String getRAMsize()

    ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
    ManagementObjectCollection moc = mc.GetInstances();
    foreach (ManagementObject item in moc)
    
       return Convert.ToString(Math.Round(Convert.ToDouble(item.Properties["TotalPhysicalMemory"].Value) / 1048576, 0)) + " MB";
    

    return "RAMsize";

【讨论】:

【参考方案9】:

此处的所有答案(包括已接受的答案)都会为您提供可用的 RAM 总量。这可能就是 OP 想要的。

但是,如果您有兴趣获得安装 RAM 的数量,那么您需要调用GetPhysicallyInstalledSystemMemory 函数。

从链接中的备注部分:

GetPhysicallyInstalledSystemMemory 函数从计算机的 SMBios 固件表中检索物理安装的 RAM 量。这可能与 GlobalMemoryStatusEx 函数报告的数量不同,该函数将 MEMORYSTATUSEX 结构的 ullTotalPhys 成员设置为可供操作系统使用的物理内存量。 操作系统可用的内存量可能少于实际安装在计算机中的内存量,因为 BIOS 和某些驱动程序可能会将内存保留为 I/O 区域对于内存映射设备,使内存对操作系统和应用程序不可用。

示例代码:

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetPhysicallyInstalledSystemMemory(out long TotalMemoryInKilobytes);

static void Main()

    long memKb;
    GetPhysicallyInstalledSystemMemory(out memKb);
    Console.WriteLine((memKb / 1024 / 1024) + " GB of RAM installed.");

【讨论】:

谢谢! 我一直在寻找这个,但在任何地方我只能看到如何找到总可用内存而不是已安装的。 它在我的虚拟机上运行不佳,尽管在主虚拟机上运行良好。【参考方案10】:

还没有人提到GetPerformanceInfo。 PInvoke signatures 可用。

此函数提供以下系统范围的信息:

提交总数 提交限制 提交峰值 物理总计 物理可用 系统缓存 内核总数 内核分页 内核未分页 页面大小 句柄计数 进程计数 线程数

PhysicalTotal 是 OP 正在寻找的,虽然该值是页数,所以要转换为字节,乘以返回的 PageSize 值。

【讨论】:

【参考方案11】:

添加对Microsoft.VisualBasicusing Microsoft.VisualBasic.Devices; 的引用。

ComputerInfo 类包含您需要的所有信息。

【讨论】:

为什么这被否决了?投票支持!这是最简单的方法,是的,你可以从 C# 中实现。 +1:有些人不喜欢从 C# 中引用 Microsoft.VisualBasic 命名空间,尽管它实际上只是作为其他所有组件的一部分安装的另一个程序集。 在 8GB 内存的 Windows7 64bit 上返回负垃圾值。这就是你被否决的原因? 对于任何对使用 (new ComputerInfo()).TotalPhysicalMemory 持怀疑态度的人,它在内存比这更多的系统上运行良好。它的返回类型是 unsigned long,所以如果没有(无效)强制转换,负数是不可能的。 var totalGBRam = Convert.ToInt32((new ComputerInfo().TotalPhysicalMemory / (Math.Pow(1024, 3))) + 0.5);【参考方案12】:

另一种方法是使用 .NET System.Management 查询工具:

string Query = "SELECT Capacity FROM Win32_PhysicalMemory";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(Query);

UInt64 Capacity = 0;
foreach (ManagementObject WniPART in searcher.Get())

    Capacity += Convert.ToUInt64(WniPART.Properties["Capacity"].Value);


return Capacity;

【讨论】:

这会在我的机器上引发 System.Management.ManagementException Out of Memory。有什么想法吗? 我喜欢这个。无需引用Microsoft.VisualBasic.Devices。而作为单线var Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast&lt;ManagementObject&gt;().Sum(x =&gt; Convert.ToInt64(x.Properties["Capacity"].Value));【参考方案13】:

您可以简单地使用此代码来获取这些信息,只需添加参考

using Microsoft.VisualBasic.Devices;

并且只需使用以下代码

    private void button1_Click(object sender, EventArgs e)
    
        getAvailableRAM();
    

    public void getAvailableRAM()
    
        ComputerInfo CI = new ComputerInfo();
        ulong mem = ulong.Parse(CI.TotalPhysicalMemory.ToString());
        richTextBox1.Text = (mem / (1024*1024) + " MB").ToString();
    

【讨论】:

在 .net 4.6 版本中找不到。我的意思是它没有找到 ComputerInfo 命名空间。甚至更多...命名空间“设备”不存在。【参考方案14】:
/*The simplest way to get/display total physical memory in VB.net (Tested)

public sub get_total_physical_mem()

    dim total_physical_memory as integer

    total_physical_memory=CInt((My.Computer.Info.TotalPhysicalMemory) / (1024 * 1024))
    MsgBox("Total Physical Memory" + CInt((My.Computer.Info.TotalPhysicalMemory) / (1024 * 1024)).ToString + "Mb" )
end sub
*/


//The simplest way to get/display total physical memory in C# (converted Form http://www.developerfusion.com/tools/convert/vb-to-csharp)

public void get_total_physical_mem()

    int total_physical_memory = 0;

    total_physical_memory = Convert.ToInt32((My.Computer.Info.TotalPhysicalMemory) /  (1024 * 1024));
    Interaction.MsgBox("Total Physical Memory" + Convert.ToInt32((My.Computer.Info.TotalPhysicalMemory) / (1024 * 1024)).ToString() + "Mb");

【讨论】:

这可能要归功于在线 Visual Basic 到 CShap 转换器。【参考方案15】:

如果您碰巧使用 Mono,那么您可能有兴趣知道 Mono 2.8(将于今年晚些时候发布)将有一个性能计数器,用于报告 Mono 运行的所有平台(包括 Windows)上的物理内存大小)。您将使用以下代码 sn-p 检索计数器的值:

using System;
using System.Diagnostics;

class app

   static void Main ()
   
       var pc = new PerformanceCounter ("Mono Memory", "Total Physical Memory");
       Console.WriteLine ("Physical RAM (bytes): 0", pc.RawValue);
   

如果您对提供性能计数器的 C 代码感兴趣,可以找到here。

【讨论】:

在任何 linux 系统上都可以正常工作,甚至在 ARM 系统上。 @harry4516 在我的 Ubuntu 系统上,不支持 PerformanceCounter【参考方案16】:

如上所述,添加对 Microsoft.VisualBasic.dll 的引用。那么获取总物理内存就这么简单(是的,我测试过):

static ulong GetTotalMemoryInBytes()

    return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;

【讨论】:

@ppumkin,在什么版本的 .NET 中,在什么版本的 Visual Studio 中?当我在具有 8 GB RAM 的 64 位机器上使用 .NET 4.5 在 VS 2012 中运行它时,它运行良好。我回 8520327168。 .NET 4, VS2010 32bit on Windows Pro 7 64bit 在 x64 上运行良好。您使用的是 32 位 VS,它可能正在编译 32 位二进制文​​件,而不会看到完整的内存大小。 在 Visual Studio 2017 和 C# .Net 4.6.1 中使用它时,我必须添加 Microsoft.VisualBasic 的引用才能使其正常工作。项目 > 添加参考 >> 程序集 > 检查 Microsoft.VisualBasic >> 确定 我注意到 GetPhysicallyInstalledSystemMemory 和 Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory new FileSizeStruct(34173231104) 31.8 GB ByteCount: 34173231104 ByteSize: GB Size: 31.8 new FileSize368(3435973) 8 32 GB 字节数:34359738368 字节大小:GB 大小:32

以上是关于您如何获得计算机的 RAM 总量?的主要内容,如果未能解决你的问题,请参考以下文章

Airflow:如何指定资源池的定量使用?

如何设置从 API 获得的产品总量的文本?

如何访问计算机的 RAM 和 ROM 的所有字节?

如何通过批处理脚本检查可用内存(RAM)?

如何计算使总和最小化的点?

如何计算运行特定 Python 程序需要多少 CPU、RAM、能量?