Làm thế nào để bạn nhận được tổng dung lượng RAM máy tính có?


88

Sử dụng C #, tôi muốn nhận tổng dung lượng RAM mà máy tính của tôi có. Với PerformanceCounter, tôi có thể nhận được số lượng ram Khả dụng, bằng cách cài đặt:

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

Nhưng tôi dường như không thể tìm ra cách để có được tổng dung lượng bộ nhớ. Tôi sẽ đi đâu để tới đó?

Cập nhật:

MagicKat: Tôi đã thấy điều đó khi tôi đang tìm kiếm, nhưng nó không hoạt động - "Bạn đang thiếu một lắp ráp hoặc tham chiếu?". Tôi đã tìm cách thêm nó vào Tài liệu tham khảo, nhưng tôi không thấy nó ở đó.

Câu trả lời:


62

Hàm Windows API GlobalMemoryStatusExcó thể được gọi bằng 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);

Sau đó sử dụng như:

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

Hoặc bạn có thể sử dụng WMI (được quản lý nhưng chậm hơn) để truy vấn TotalPhysicalMemorytrong Win32_ComputerSystemlớp.


2
Nó không hoạt động ... long ramuse = (long) stat.TotalPhysical; long ramavailable = (dài) stat.AvailablePhysical; ramtotal dài = ramavailable + ramuse; int phần trăm = (int) ((float) ramuse / ramtotal * 100); phần trăm đang nói với tôi "70" và tổng số liên tục thay đổi, cho hoặc nhận 100. phải là 72%
Joel

5
Mã hoạt động, chỉ bạn không cần sử dụng 'NativeMethods' để lấy kích thước của đối tượng, bạn chỉ cần nói như thế này: this.dwLength = (uint)Marshal.SizeOf(this);và nó hoạt động giống nhau (tôi đã gặp sự cố khi sử dụng NativeMethods nên bản sửa lỗi này hiện hoạt động).
Cipi

2
"NativeMethods" là không gian tên của kiểu. Lệnh gọi đến SizeOf có thể được thay đổi nếu bạn muốn.
Philip Rieck

2
@Corelgott Vô dụng vì nó cung cấp thông tin cập nhật? Ý tôi là, mỗi khi tôi kiểm tra kênh thời tiết, nó sẽ đưa ra những thông tin khác nhau, nhưng tôi sẽ không đi quá xa để gọi nó là hoàn toàn vô dụng. Tôi thậm chí không chắc bạn sẽ muốn chức năng này làm gì nếu nó không trả về thông tin có khả năng khác nhau mỗi lần - nó có nên "khóa" kết quả sau lần gọi đầu tiên và sau đó trả về dữ liệu cũ sau đó không? Điều đó sẽ hữu ích hơn theo cách nào?
Philip Rieck

2
Một chút muộn cho bữa tiệc nhưng tôi đã xảy ra chủ đề này và câu trả lời này không chính xác. GlobalMemoryStatusEx không nhất thiết (và thường sẽ không) cung cấp số lượng RAM thực được cài đặt trên máy, nó cung cấp số lượng có sẵn cho hệ điều hành, hầu như luôn luôn khác với số lượng được cài đặt do bộ nhớ dành riêng cho trình điều khiển, v.v. Để có được dung lượng RAM thực được cài đặt, bạn sẽ gọi hàm GetPhysentlyInstalledSystemMemory để trả về tổng RAM thích hợp. msdn.microsoft.com/en-us/library/windows/desktop/…
Mike Johnson

182

Thêm tham chiếu đến Microsoft.VisualBasicvà a using Microsoft.VisualBasic.Devices;.

Các ComputerInfolớp có tất cả các thông tin mà bạn cần.


10
Tại sao điều này lại bị bỏ phiếu? Đã bình chọn trở lại! Đây là cách dễ nhất để thực hiện và bạn có thể làm được điều này từ C #.
Paul Batum 19-08

54
+1: Một số người có ác cảm với việc tham chiếu không gian tên Microsoft.VisualBasic từ C #, mặc dù nó thực sự chỉ là một assembly khác được cài đặt như một phần của mọi thứ khác.
Bevan

2
Trả về giá trị rác âm trên Windows7 64bit với ram 8gb. Đó là lý do tại sao bạn bị bỏ phiếu?
Piotr Kula

6
Đối với bất kỳ ai ít sử dụng (new ComputerInfo ()). TotalPhysicalMemory, nó hoạt động tốt trên một hệ thống có nhiều bộ nhớ hơn thế. Kiểu trả về của nó là dài không có dấu, vì vậy không thể có một số âm nếu không có kiểu ép (không hợp lệ).
Miles Strombach

6
var totalGBRam = Convert.ToInt32 ((new ComputerInfo (). TotalPhysicalMemory / (Math.Pow (1024, 3))) + 0,5);
Sean

63

Thêm tham chiếu đến Microsoft.VisualBasic.dll, như ai đó đã đề cập ở trên. Sau đó, nhận tổng bộ nhớ vật lý đơn giản như sau (vâng, tôi đã thử nghiệm nó):

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

4
@ppumkin, trong phiên bản .NET và phiên bản Visual Studio nào? Khi tôi chạy nó trong VS 2012 bằng cách sử dụng .NET 4.5 trên máy 64-bit với 8 GB RAM, nó hoạt động tốt. Tôi lấy lại 8520327168.
Ryan Lundy

.NET 4, VS2010 32bit trên Windows Pro 7 64bit
Piotr Kula

2
Hoạt động tốt trên x64. Bạn đang sử dụng VS 32 bit có thể đang biên dịch các tệp nhị phân 32 bit mà sẽ không thấy kích thước bộ nhớ đầy đủ.
Lucas Teske

2
Khi sử dụng điều này trong Visual Studio 2017 với C # .Net 4.6.1, tôi đã phải thêm tham chiếu cho Microsoft.VisualBasic để làm cho điều này hoạt động. Dự án> Thêm tài liệu tham khảo >> Assemblies> Kiểm tra Microsoft.VisualBasic >> OK
WebLuke

Tôi nhận thấy sự khác biệt giữa GetPhysallyInstalledSystemMemory và Microsoft.VisualBasic.Devices.ComputerInfo (). TotalPhysicalMemory mới FileSizeStruct (34173231104) {31.8 GB} ByteCount: 34173231104 ByteSize: GB Size: 31.897368 mới GB Kích thước: 32
fanuc_bob

36

Tất cả các câu trả lời ở đây, bao gồm cả câu được chấp nhận, sẽ cung cấp cho bạn tổng dung lượng RAM có sẵn để sử dụng. Và đó có thể là những gì OP muốn.

Nhưng nếu bạn quan tâm đến việc nhận được dung lượng RAM đã cài đặt , thì bạn sẽ muốn thực hiện cuộc gọi đến chức năng GetPhysentlyInstalledSystemMemory .

Từ liên kết, trong phần Nhận xét:

Hàm GetPhysallyInstalledSystemMemory truy xuất lượng RAM được cài đặt vật lý từ bảng phần sụn SMBIOS của máy tính. Điều này có thể khác với dung lượng được báo cáo bởi hàm GlobalMemoryStatusEx , hàm này đặt thành viên ullTotalPhys của cấu trúc MEMORYSTATUSEX thành dung lượng bộ nhớ vật lý có sẵn để hệ điều hành sử dụng. Dung lượng bộ nhớ có sẵn cho hệ điều hành có thể ít hơn dung lượng bộ nhớ được cài đặt vật lý trong máy tính vì BIOS và một số trình điều khiển có thể dự trữ bộ nhớ dưới dạng vùng I / O cho các thiết bị được ánh xạ bộ nhớ, làm cho bộ nhớ không khả dụng với hệ điều hành và các ứng dụng.

Mã mẫu:

[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
Cảm ơn bạn! Tôi đã tìm kiếm chính xác điều này nhưng ở khắp mọi nơi, tôi chỉ có thể thấy cách tìm tổng bộ nhớ khả dụng hơn là bộ nhớ đã cài đặt.
SM

Mặc dù vậy, nó không hoạt động tốt trên máy ảo của tôi, mặc dù hoạt động hoàn hảo trên máy chính.
SM

31

Nếu bạn đang sử dụng Mono, thì bạn có thể muốn biết rằng Mono 2.8 (sẽ được phát hành vào cuối năm nay) sẽ có bộ đếm hiệu suất báo cáo kích thước bộ nhớ vật lý trên tất cả các nền tảng Mono chạy trên (bao gồm cả Windows). Bạn sẽ truy xuất giá trị của bộ đếm bằng đoạn mã sau:

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

Nếu bạn quan tâm đến mã C cung cấp bộ đếm hiệu suất, bạn có thể tìm thấy mã này tại đây .


hoạt động tốt trên bất kỳ hệ thống linux nào, ngay cả trên hệ thống ARM.
harry4516

14

Một cách khác để làm điều này, là sử dụng phương tiện truy vấn .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;

Điều này đang ném System.Management.ManagementException ra khỏi bộ nhớ trên máy tính của tôi. Có ý kiến ​​gì không?
Amar

2
Tôi thích cái này. Không cần tham khảo Microsoft.VisualBasic.Devices. Và như một lớp lótvar Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
VDWWD

10

Đối với những người đang sử dụng .net Core 3.0, không cần sử dụng PInvokenền tảng để có được bộ nhớ vật lý khả dụng. Các GClớp đã được thêm vào một phương pháp mới GC.GetGCMemoryInfomà trả về một GCMemoryInfo Structvới TotalAvailableMemoryBytesnhư một tài sản. Thuộc tính này trả về tổng bộ nhớ khả dụng cho bộ thu gom rác. (Cùng giá trị với MEMORYSTATUSEX)

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

Câu trả lời yêu thích của tôi. Cảm ơn.
Matas Vaitkevicius

7

bạn chỉ cần sử dụng mã này để lấy những thông tin đó, chỉ cần thêm tài liệu tham khảo

using Microsoft.VisualBasic.Devices;

và chỉ cần sử dụng mã sau

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

không tìm thấy trong phiên bản .net 4.6. Tôi có nghĩa là nó cung cấp không gian tên ComputerInfo không được tìm thấy. thậm chí nhiều hơn ... không gian tên 'Thiết bị' không tồn tại.
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

Bạn có thể sử dụng WMI. Đã tìm thấy một đoạn trích.

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

Lưu ý rằng Setkhông còn cần thiết cho VB.NET, đây có phải là mã VB6 không?
jrh

2

Hàm này ( ManagementQuery) hoạt động trên Windows XP trở lên:

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

Sử dụng:

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

2
BytesToMbchức năng đó đến từ đâu?
Cee McSharpface

@dlatikay đó là bên trong fuction: private static double BytesToMb (byte dài) {return Math.Round (byte / 1024d / 1024d, 2); }
Lance

1

Tương thích với .Net và Mono (được thử nghiệm với Win10 / FreeBSD / CentOS)

Sử dụng ComputerInfomã nguồn và PerformanceCountercác s cho Mono và làm bản sao lưu cho .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

Chưa ai đề cập đến GetPerformanceInfo . Chữ ký PInvoke có sẵn.

Chức năng này cung cấp thông tin toàn hệ thống sau:

  • Tổng số tiền
  • CommitLimit
  • Cam kết
  • Tổng giá trị vật lý
  • Vật lý có sẵn
  • SystemCache
  • KernelTotal
  • KernelPaged
  • KernelNonpaged
  • Kích thước trang
  • HandleCount
  • ProcessCount
  • Số đề

PhysicalTotallà những gì OP đang tìm kiếm, mặc dù giá trị là số trang, vì vậy, để chuyển đổi thành byte, hãy nhân với PageSizegiá trị được trả về.


0

.NIT có giới hạn về dung lượng bộ nhớ mà nó có thể truy cập trong tổng số. Tỷ lệ phần trăm và sau đó là 2 GB xp là mức trần cứng.

Bạn có thể có 4 GB trong đó và nó sẽ giết ứng dụng khi đạt mức 2GB.

Ngoài ra ở chế độ 64 bit, có một tỷ lệ bộ nhớ bạn có thể sử dụng ngoài hệ thống, vì vậy tôi không chắc liệu bạn có thể yêu cầu toàn bộ hay không hoặc điều này có được bảo vệ cụ thể hay không.


/Không/. Tổng bộ nhớ vật lý có nghĩa là bộ nhớ thực được cài đặt vật lý.
Matthew Flaschen

Trên thực tế, DevelopChris là chính xác. Nếu bạn gọi GlobalMemoryStatusEx trên máy XP với 4 Gig Ram, nó sẽ báo rằng chỉ có 3 Gig được cài đặt.
epotter

Ngoài ra, việc sử dụng WMI để truy vấn TotalPhysicalMemory trong Win32_ComputerSystem hoặc Win32_LogicalMemoryConfiguration cũng cho kết quả sai.
epotter

cảm ơn bạn, không phải là tôi không hiểu câu hỏi mà bạn phải sử dụng một nguồn khác cho thông tin ngoài thư viện .net.
phát triểnChris

Câu trả lời này là câu trả lời duy nhất có ý nghĩa. Tôi đã mệt mỏi nó bây giờ trên Win 64 8Gb ram sử dụng VisualBasic tham chiếu. Tôi nhận được các giá trị âm rác.
Piotr Kula

-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
Đó có thể là nhờ các bộ chuyển đổi Visual Basic sang CShap trực tuyến.
Nick Binnet
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.