繁体   English   中英

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

[英]How do you get total amount of RAM the computer has?

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

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

但我似乎无法找到一种方法来获得 memory 的总量。我将如何 go 这样做呢?

更新:

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

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

ComputerInfo类具有您需要的所有信息。

添加对 Microsoft.VisualBasic.dll 的引用,正如上面提到的那样。 然后获得总物理内存就这么简单(是的,我测试过):

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

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

  [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(托管但速度较慢)来查询Win32_ComputerSystem类中的TotalPhysicalMemory

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

如果您碰巧使用 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 代码感兴趣,可以在此处找到。

另一种方法是使用 .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;

对于使用.net Core 3.0 ,无需使用PInvoke平台来获取可用的物理内存。 GC类添加了一个新方法GC.GetGCMemoryInfo ,该方法返回一个GCMemoryInfo StructTotalAvailableMemoryBytes作为属性。 此属性返回垃圾收集器的总可用内存。(与 MEMORYSTATUSEX 相同的值)

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

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

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();
    }

你可以使用 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
// 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";
}

此函数 ( 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"))));

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

ComputerInfo源代码和PerformanceCounter用于 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)))
            };
        }
    }
}

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

你可以有 4 GB,当它达到 2 GB 时它会杀死应用程序。

同样在 64 位模式下,您可以在系统外使用一定比例的内存,所以我不确定您是否可以要求整个事情,或者是否特别防范。

还没有人提到GetPerformanceInfo PInvoke 签名可用。

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

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

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

这是另一种更简单的方法,使用 .net:

// total memory
long totalPhysicalMemory = My.Computer.Info.TotalPhysicalMemory;

// unused memory
long availablePhysicalMemory = My.Computer.Info.AvailablePhysicalMemory;

// used memory
long usedMemory = totalPhysicalMemory - availablePhysicalMemory;

Linux (.Net Core)上工作的解决方案。 GitHub/Hardware.Info启发。 优化为具有最小的 memory 分配和平均检索需要 0.020 毫秒。

private static readonly object _linuxMemoryLock = new();
private static readonly char[] _arrayForMemInfoRead = new char[200];

public static void GetBytesCountOnLinux(out ulong availableBytes, out ulong totalBytes)
{
    lock (_linuxMemoryLock) // lock because of reusing static fields due to optimization
    {
        totalBytes = GetBytesCountFromLinuxMemInfo(token: "MemTotal:", refreshFromFile: true);
        availableBytes = GetBytesCountFromLinuxMemInfo(token: "MemAvailable:", refreshFromFile: false);
    }
}

private static ulong GetBytesCountFromLinuxMemInfo(string token, bool refreshFromFile)
{
    // NOTE: Using the linux file /proc/meminfo which is refreshed frequently and starts with:
    //MemTotal:        7837208 kB
    //MemFree:          190612 kB
    //MemAvailable:    5657580 kB

    var readSpan = _arrayForMemInfoRead.AsSpan();

    if (refreshFromFile)
    {
        using var fileStream = new FileStream("/proc/meminfo", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        using var reader = new StreamReader(fileStream, Encoding.UTF8, leaveOpen: true);

        reader.ReadBlock(readSpan);
    }

    var tokenIndex = readSpan.IndexOf(token);

    var fromTokenSpan = readSpan.Slice(tokenIndex + token.Length);

    var kbIndex = fromTokenSpan.IndexOf("kB");

    var notTrimmedSpan = fromTokenSpan.Slice(0, kbIndex);

    var trimmedSpan = notTrimmedSpan.Trim(' ');

    var kBytesCount = ulong.Parse(trimmedSpan);

    var bytesCount = kBytesCount * 1024;

    return bytesCount;
}

Linux 和 Windows 在一起- 便于复制粘贴。 Windows 代码取自已接受的答案

public static void GetRamBytes(out ulong availableBytes, out ulong totalBytes)
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    {
        GetBytesCountOnLinux(out availableBytes, out totalBytes);
    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        GetBytesCountOnWindows(out availableBytes, out totalBytes);
    }
    else
    {
        throw new NotImplementedException("Not implemented for OS: " + Environment.OSVersion);
    }
}

private static readonly object _winMemoryLock = new();
private static readonly MEMORYSTATUSEX _memStatus = new();

private static void GetBytesCountOnWindows(out ulong availableBytes, out ulong totalBytes)
{
    lock (_winMemoryLock) // lock because of reusing the static class _memStatus
    {
        GlobalMemoryStatusEx(_memStatus);

        availableBytes = _memStatus.ullAvailPhys;
        totalBytes = _memStatus.ullTotalPhys;
    }
}

[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(MEMORYSTATUSEX));
    }
}

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GlobalMemoryStatusEx([In] [Out] MEMORYSTATUSEX lpBuffer);
/*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");
}

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)

questa procedura salva in "a" la ram totale presente in GB


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)

questa procedura salva in "b" il valore della ram in GB effettivamente disponibile


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM