您如何获得计算机的 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
源代码和PerformanceCounter
s 用于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.VisualBasic
和using 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<ManagementObject>().Sum(x => 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 总量?的主要内容,如果未能解决你的问题,请参考以下文章