Bagaimana Anda mendapatkan jumlah total RAM yang dimiliki komputer?

89

Menggunakan C #, saya ingin mendapatkan jumlah total RAM yang dimiliki komputer saya. Dengan PerformanceCounter saya bisa mendapatkan jumlah ram yang tersedia, dengan mengatur:

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

Tapi sepertinya saya tidak bisa menemukan cara untuk mendapatkan jumlah total memori. Bagaimana saya akan melakukan ini?

Memperbarui:

MagicKat: Saya melihatnya ketika saya sedang mencari, tetapi tidak berhasil - "Apakah Anda melewatkan rakitan atau referensi?". Saya telah melihat untuk menambahkannya ke Referensi, tetapi saya tidak melihatnya di sana.

Joel
sumber

Jawaban:

63

Fungsi Windows API GlobalMemoryStatusExdapat dipanggil dengan 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);

Kemudian gunakan seperti:

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

Atau Anda dapat menggunakan WMI (dikelola tetapi lebih lambat) untuk melakukan kueri TotalPhysicalMemorydi Win32_ComputerSystemkelas.

Philip Rieck
sumber
2
Itu tidak berfungsi ... long ramuse = (long) stat.TotalPhysical; long ramavailable = (panjang) stat.AvailablePhysical; ramtotal panjang = ramtotal + ramuse; int persen = (int) ((float) ramuse / ramtotal * 100); persen memberi tahu saya "70" dan total terus berubah, memberi atau menerima 100. harus 72%
Joel
5
Kode berfungsi, hanya Anda tidak perlu menggunakan 'NativeMethods' untuk mendapatkan ukuran objek, Anda cukup mengatakan seperti ini: this.dwLength = (uint)Marshal.SizeOf(this);dan berfungsi sama (saya kesulitan menggunakan NativeMethods jadi perbaikan ini sekarang berfungsi).
Cipi
2
"NativeMethods" adalah namespace dari jenis tersebut. Panggilan ke SizeOf dapat diubah jika Anda mau.
Philip Rieck
2
@Corelgott Tidak berguna karena memberikan informasi terkini? Maksud saya, setiap kali saya memeriksa saluran cuaca, itu memberikan informasi yang berbeda, tetapi saya tidak akan menyebutnya sama sekali tidak berguna. Saya bahkan tidak yakin apa yang Anda ingin fungsi ini lakukan jika tidak mengembalikan informasi yang berpotensi berbeda setiap kali - haruskah "mengunci" hasil setelah pemanggilan pertama dan kemudian mengembalikan data usang setelah itu? Dalam hal apa itu lebih berguna?
Philip Rieck
2
Agak terlambat ke pesta tetapi saya kebetulan di utas ini dan jawaban ini tidak benar. GlobalMemoryStatusEx tidak selalu (dan seringkali tidak) memberikan jumlah sebenarnya dari RAM yang diinstal pada mesin, ini memberikan jumlah yang tersedia untuk OS yang hampir selalu berbeda dari jumlah yang diinstal karena memori yang dicadangkan untuk driver, dll. Untuk mendapatkan jumlah RAM yang terpasang sebenarnya Anda ingin memanggil fungsi GetPhysicallyInstalledSystemMemory yang mengembalikan total RAM yang sesuai. msdn.microsoft.com/en-us/library/windows/desktop/…
Mike Johnson
183

Tambahkan referensi ke Microsoft.VisualBasicdan a using Microsoft.VisualBasic.Devices;.

The ComputerInfokelas memiliki semua informasi yang Anda butuhkan.

MagicKat
sumber
10
Mengapa ini ditolak? Telah memilih kembali! Ini adalah cara termudah untuk melakukannya, dan ya Anda bisa melakukannya dari C #.
Paul Batum
54
+1: Beberapa orang enggan mereferensikan namespace Microsoft.VisualBasic dari C #, meskipun sebenarnya itu hanya rakitan lain yang diinstal sebagai bagian dari yang lainnya.
Bevan
2
Kembalikan nilai sampah negatif pada Windows7 64bit dengan ram 8gb. Itulah mengapa Anda turun memilih?
Piotr Kula
6
Bagi siapa pun yang ragu menggunakan (ComputerInfo baru ()). TotalPhysicalMemory, ini berfungsi dengan baik pada sistem dengan lebih banyak memori daripada itu. Jenis kembaliannya adalah unsigned long, jadi angka negatif tidak mungkin dilakukan tanpa cast (tidak valid).
Miles Strombach
6
var totalGBRam = Convert.ToInt32 ((baru ComputerInfo (). TotalPhysicalMemory / (Math.Pow (1024, 3))) + 0,5);
Sean
63

Tambahkan referensi ke Microsoft.VisualBasic.dll, seperti yang disebutkan di atas. Maka mendapatkan memori fisik total sesederhana ini (ya, saya mengujinya):

static ulong GetTotalMemoryInBytes()
{
    return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
}
Ryan Lundy
sumber
4
@ppumkin, dalam versi .NET apa, dan dalam versi Visual Studio apa? Ketika saya menjalankannya di VS 2012 menggunakan .NET 4.5 pada mesin 64-bit dengan RAM 8 GB, itu berfungsi dengan baik. Saya kembali 8520327168.
Ryan Lundy
.NET 4, VS2010 32bit pada Windows Pro 7 64bit
Piotr Kula
2
Berfungsi dengan baik pada x64. Anda menggunakan VS 32 bit yang mungkin sedang mengompilasi binari 32 bit yang tidak akan melihat ukuran memori penuh.
Lucas Teske
2
Saat menggunakan ini di Visual Studio 2017 dengan C # .Net 4.6.1, saya memang harus menambahkan referensi untuk Microsoft.VisualBasic agar ini berfungsi. Proyek> Tambahkan Referensi >> Assemblies> Periksa Microsoft.VisualBasic >> OK
WebLuke
Saya melihat perbedaan antara GetPhysicallyInstalledSystemMemory dan Microsoft.VisualBasic.Devices.ComputerInfo (). TotalPhysicalMemory new FileSizeStruct (34173231104) {31,8 GB} ByteCount: 34173231104 ByteSize: GB Size: 31.8 new FileSizeStruct (34359738) Ukuran GB: 32
fanuc_bob
36

Semua jawaban di sini, termasuk yang diterima, akan memberi Anda jumlah total RAM yang tersedia untuk digunakan. Dan mungkin itulah yang diinginkan OP.

Tetapi jika Anda tertarik untuk mendapatkan jumlah RAM yang terpasang , maka Anda sebaiknya memanggil fungsi GetPhysicallyInstalledSystemMemory .

Dari tautan, di bagian Keterangan:

Fungsi GetPhysicallyInstalledSystemMemory mengambil jumlah RAM yang diinstal secara fisik dari tabel firmware SMBIOS komputer. Ini dapat berbeda dari jumlah yang dilaporkan oleh fungsi GlobalMemoryStatusEx , yang menetapkan anggota ullTotalPhys struktur MEMORYSTATUSEX ke jumlah memori fisik yang tersedia untuk digunakan oleh sistem operasi. Jumlah memori yang tersedia untuk sistem operasi bisa kurang dari jumlah memori yang terpasang secara fisik di komputer karena BIOS dan beberapa driver mungkin menyimpan memori sebagai wilayah I / O untuk perangkat yang dipetakan memori, membuat memori tidak tersedia untuk sistem operasi dan aplikasi.

Kode sampel:

[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.");
}
sstan
sumber
1
Terima kasih! Saya mencari persis ini tetapi di mana-mana saya hanya dapat melihat bagaimana menemukan total memori yang tersedia daripada yang diinstal.
SM
Itu tidak berfungsi dengan baik di mesin virtual saya, meskipun berfungsi dengan sempurna di mesin utama.
SM
31

Jika Anda kebetulan menggunakan Mono, Anda mungkin tertarik untuk mengetahui bahwa Mono 2.8 (akan dirilis akhir tahun ini) akan memiliki penghitung kinerja yang melaporkan ukuran memori fisik pada semua platform yang dijalankan oleh Mono (termasuk Windows). Anda akan mengambil nilai penghitung menggunakan cuplikan kode ini:

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

Jika Anda tertarik dengan kode C yang menyediakan penghitung kinerja, itu dapat ditemukan di sini .

grendel
sumber
berfungsi dengan baik pada sistem linux apa pun, bahkan pada sistem ARM.
harry4516
@ harry4516 di sistem Ubuntu saya, PerformanceCounter tidak didukung
Carlos Liu
14

Cara lain untuk melakukannya, adalah dengan menggunakan fasilitas querying System.Management .NET:

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;
zgerd
sumber
Ini membuang System.Management.ManagementException Out of Memory di komputer saya. Ada ide?
Amar
2
Saya suka yang ini. Tidak perlu referensi Microsoft.VisualBasic.Devices. Dan sebagai satu barisvar Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
VDWWD
10

Bagi mereka yang sedang menggunakan .net Core 3.0tidak perlu menggunakan PInvokeplatform untuk mendapatkan memori fisik yang tersedia. The GCkelas telah menambahkan metode baru GC.GetGCMemoryInfoyang mengembalikan GCMemoryInfo Structdengan TotalAvailableMemoryBytessebagai properti. Properti ini mengembalikan total memori yang tersedia untuk pengumpul sampah. (Nilai yang sama dengan MEMORYSTATUSEX)

var gcMemoryInfo = GC.GetGCMemoryInfo();
installedMemory = gcMemoryInfo.TotalAvailableMemoryBytes;
// it will give the size of memory in MB
var physicalMemory = (double) installedMemory / 1048576.0;
BRAHIM Kamel
sumber
Jawaban favorit saya. Terima kasih.
Matas Vaitkevicius
7

Anda cukup menggunakan kode ini untuk mendapatkan informasi tersebut, cukup tambahkan referensi

using Microsoft.VisualBasic.Devices;

dan cukup gunakan kode berikut

    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();
    }
Nilan Niyomal
sumber
tidak ditemukan dalam versi .net 4.6. Maksud saya memberikan namespace ComputerInfo tidak ditemukan. bahkan lebih ... namespace 'Perangkat' tidak ada.
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";
}
Mehul Sant
sumber
5

Anda bisa menggunakan WMI. Menemukan potongan.

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
CodeRot
sumber
Perhatikan bahwa Settidak lagi diperlukan untuk VB.NET, apakah ini kode VB6?
jrh
2

Fungsi ini ( ManagementQuery) berfungsi di Windows XP dan yang lebih baru:

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

Pemakaian:

Console.WriteLine(BytesToMb(Convert.ToInt64(ManagementQuery("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem", "TotalPhysicalMemory", "root\\CIMV2"))));
Tombak
sumber
2
dari mana BytesToMbasalnya fungsi itu?
Cee McSharpface
@dlatikay itu fungsi dalamnya: private static double BytesToMb (byte panjang) {return Math.Round (bytes / 1024d / 1024d, 2); }
Lance
1

Kompatibel dengan .Net dan Mono (diuji dengan Win10 / FreeBSD / CentOS)

Menggunakan ComputerInfokode sumber dan PerformanceCounters untuk Mono dan sebagai cadangan untuk .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)))
            };
        }
    }
}
Soroush Falahati
sumber
0

Belum ada yang menyebutkan GetPerformanceInfo . Tanda tangan PInvoke tersedia.

Fungsi ini membuat informasi seluruh sistem berikut tersedia:

  • CommitTotal
  • CommitLimit
  • CommitPeak
  • PhysicalTotal
  • Fisik Tersedia
  • SystemCache
  • KernelTotal
  • KernelPaged
  • KernelNonpaged
  • Ukuran halaman
  • HandleCount
  • ProcessCount
  • ThreadCount

PhysicalTotaladalah yang dicari OP, meskipun nilainya adalah jumlah halaman, jadi untuk dikonversi ke byte, kalikan dengan PageSizenilai yang dikembalikan.

Roman Starkov
sumber
0

.NIT memiliki batas jumlah total memori yang dapat diaksesnya. Ada persentase, dan kemudian 2 GB di xp adalah langit-langit yang keras.

Anda dapat memiliki 4 GB di dalamnya, dan itu akan mematikan aplikasi ketika mencapai 2 GB.

Juga dalam mode 64 bit, ada persentase memori yang dapat Anda gunakan di luar sistem, jadi saya tidak yakin apakah Anda dapat meminta semuanya atau apakah ini secara khusus dilindungi.

DevelopingChris
sumber
/Tidak/. Memori fisik total berarti memori sebenarnya yang terpasang secara fisik.
Matthew Flaschen
Sebenarnya, DevelopingChris benar. Jika Anda memanggil GlobalMemoryStatusEx pada mesin XP dengan 4 Gig of Ram, itu akan melaporkan bahwa hanya ada 3 Gig yang diinstal.
epotter
Selain itu, menggunakan WMI untuk meminta TotalPhysicalMemory di Win32_ComputerSystem atau Win32_LogicalMemoryConfiguration juga menghasilkan hasil yang salah.
epotter
terima kasih, bukan karena saya tidak mengerti pertanyaannya bahwa Anda harus menggunakan sumber yang berbeda untuk informasi selain pustaka .net.
DevelopingChris
Jawaban ini adalah satu-satunya jawaban yang masuk akal. Saya lelah sekarang di ram Win 64 8Gb menggunakan referensi VisualBasic. Saya mendapatkan nilai negatif sampah.
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");
}
SuMeeT ShaHaPeTi
sumber
6
Itu mungkin berkat konverter Visual Basic ke CShap online.
Nick Binnet