【问题标题】:How do you get total amount of RAM the computer has?您如何获得计算机的 RAM 总量?
【发布时间】:2026-01-19 03:15:01
【问题描述】:

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

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

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

更新:

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

【问题讨论】:

    标签: c# memory performancecounter


    【解决方案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】:

        还没有人提到GetPerformanceInfoPInvoke 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