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


88

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

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

但是我似乎找不到找到总内存量的方法。我将如何去做呢?

更新:

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

Answers:


62

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

  [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);

然后使用像:

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

或者,您可以使用WMI(托管的但速度较慢)TotalPhysicalMemoryWin32_ComputerSystem类中查询。


2
那是行不通的... long ramuse =(long)stat.TotalPhysical; long ramavailable =(long)stat.AvailablePhysical; 长ramtotal =可用ram + ramuse;int percent =(int)((float)ramuse / ramtotal * 100); 百分比告诉我“ 70”,并且总数不断变化,给予或接受100。应为72%
Joel

5
该代码有效,只有您不需要使用'NativeMethods'来获取对象的大小,您可以这样简单地说:this.dwLength = (uint)Marshal.SizeOf(this);并且它的工作原理相同(我在使用NativeMethods时遇到了麻烦,因此此修复程序现在可以工作)。
Cipi

2
“ NativeMethods”是该类型的名称空间。如果愿意,可以更改对SizeOf的调用。
菲利普·里克

2
@Corelgott没用,因为它放弃了最新信息吗?我的意思是,每次检查天气频道时,它都会提供不同的信息,但我不会称其为完全无用。我什至不确定如果该函数每次都没有返回潜在的不同信息,那么您希望该函数做什么?它应在第一次调用后“锁定”结果,然后在此之后返回陈旧数据吗?哪种方式会更有用?
Philip Rieck

2
聚会晚了一点,但我碰巧遇到了这个问题,这个答案是不正确的。GlobalMemoryStatusEx不一定(而且通常不会)给出计算机上实际安装的RAM数量,而是给出操作系统可用的数量,该数量几乎总是与由于为驱动程序保留的内存而导致的安装数量不同。 。要获取实际安装的RAM数量,您需要调用GetPhysicallyInstalledSystemMemory函数,该函数返回正确的总RAM。msdn.microsoft.com/en-us/library/windows/desktop/…–
Mike Johnson,

182

Microsoft.VisualBasic和添加引用using Microsoft.VisualBasic.Devices;

ComputerInfo类有你需要的所有信息。


10
为什么这在地球上被否决了?投票回去!这是最简单的方法,是的,您可以从C#中做到这一点。
Paul Batum

54
+1:有些人讨厌从C#引用Microsoft.VisualBasic命名空间,尽管实际上它只是另一个程序集,已作为其他所有程序的一部分安装。
Bevan

2
在具有8GB内存的Windows7 64bit上返回负垃圾值。那就是为什么你被否决?
Piotr Kula 2012年

6
对于不愿使用(new ComputerInfo())。TotalPhysicalMemory的任何人,它在具有更多内存的系统上都能正常工作。其返回类型为unsigned long,因此,如果没有(无效)强制类型转换,则不可能使用负数。
Miles Strombach

6
var totalGBRam = Convert.ToInt32((new ComputerInfo()。TotalPhysicalMemory /(Math.Pow(1024,3)))+ 0.5);
肖恩

63

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

static ulong GetTotalMemoryInBytes()
{
    return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
}

4
@ ppumkin,.NET的哪个版本以及Visual Studio的哪个版本?当我在具有8 GB RAM的64位计算机上使用.NET 4.5在VS 2012中运行它时,它工作正常。我回来8520327168。–
Ryan Lundy

.NET 4,Windows Pro 7 64位上的VS2010 32位
Piotr Kula

2
在x64上可以正常工作。您使用的是32位VS,可能正在编译32位二进制文​​件,而看不到完整的内存大小。
卢卡斯·特斯克

2
在带有C#.Net 4.6.1的Visual Studio 2017中使用此功能时,我确实必须添加Microsoft.VisualBasic的引用才能使其正常工作。项目>添加参考>>程序集>检查Microsoft.VisualBasic >>确定
WebLuke

我注意到GetPhysicallyInstalledSystemMemory和Microsoft.VisualBasic.Devices.ComputerInfo()。TotalPhysicalMemory之间的区别new FileSizeStruct(34173231104){31.8 GB} ByteCount:34173231104 ByteSize:GB大小:31.8 new FileSizeStruct(34359738368){32 GB} ByteCount:34359738368 ByteSize GB大小:32
fanuc_bob,

36

这里的所有答案,包括已接受的答案,将为您提供可用的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.");
}

1
谢谢!我一直在寻找这个,但是到处都只能看到如何找到总可用内存,而不是已安装的内存。
SM

尽管在主虚拟机上运行良好,但它在我的虚拟机上无法正常运行。
SM

31

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

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代码感兴趣,可以在此处找到。


在任何linux系统上都可以正常工作,甚至在ARM系统上也可以。
harry4516

14

另一种方法是使用.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内存不足。有任何想法吗?
Amar

2
我喜欢这个。无需参考Microsoft.VisualBasic.Devices。并且作为var Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
单线

10

对于正在使用的用户.net Core 3.0,无需使用PInvoke平台即可获取可用的物理内存。本GC类增加了新的方法GC.GetGCMemoryInfo,它返回一个GCMemoryInfo Struct带有TotalAvailableMemoryBytes作为属性。此属性返回垃圾收集器的总可用内存。(与MEMORYSTATUSEX相同的值)

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

我最喜欢的答案。谢谢。
Matas Vaitkevicius,

7

您只需使用此代码即可获取这些信息,只需添加参考即可

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命名空间未找到。甚至更多...名称空间“设备”不存在。
gumuruh

5
// 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";
}

5

您可以使用WMI。找到一个摘录。

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

请注意,SetVB.NET不再需要此VB6代码吗?
jrh

2

此功能(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"))));

2
BytesToMb功能从何而来?
Cee McSharpface '17

@dlatikay是内部功能:私有静态双字节BytesToMb(长字节){return Math.Round(bytes / 1024d / 1024d,2); }
Lance

1

与.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)))
            };
        }
    }
}

0

还没有人提到GetPerformanceInfoP调用签名可用。

此功能使以下系统范围的信息可用:

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

PhysicalTotalOP正在寻找的内容,尽管该值是页面数,所以要转换为字节,请乘以PageSize返回的值。


0

.NIT对它可以访问的总内存量有限制。有一个百分比,然后xp中的2 GB是硬上限。

您可能有4 GB,当它达到2GB时它将杀死该应用程序。

同样在64位模式下,您可以在系统外部使用一定百分比的内存,因此我不确定是否可以要求全部内容或是否需要特别注意。


/没有/。总物理内存是指实际安装的实际内存。
马修·弗拉申

实际上,DevelopingChris是正确的。如果在具有4 Gig Ram的XP机器上调用GlobalMemoryStatusEx,它将报告仅安装了3 Gig。
epotter

此外,使用WMI查询Win32_ComputerSystem或Win32_LogicalMemoryConfiguration中的TotalPhysicalMemory也会产生错误的结果。
epotter

谢谢,不是我不明白这个问题,不是您必须使用.net库以外的其他信息源。
DevelopingChris

这个答案是唯一有意义的答案。我现在使用引用的VisualBasic在Win 64 8Gb ram上累了。我得到垃圾负值。
Piotr Kula 2012年

-3
/*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");
}

6
这可能要归功于从Visual Basic到CShap的在线转换器。
Nick Binnet
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.