Bilgisayarın sahip olduğu toplam RAM miktarını nasıl elde edersiniz?


89

C # kullanarak, bilgisayarımın sahip olduğu toplam RAM miktarını almak istiyorum. PerformanceCounter ile, aşağıdakileri ayarlayarak Kullanılabilir ram miktarını alabilirim:

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

Ama toplam hafıza miktarını elde etmenin bir yolunu bulamıyorum. Bunu nasıl yapacağım?

Güncelleme:

MagicKat: Bunu ararken gördüm ama işe yaramıyor - "Bir montajı veya referansı mı kaçırıyorsunuz?". Bunu Referanslara eklemek istedim, ama orada göremiyorum.

Yanıtlar:


63

Windows API işlevi GlobalMemoryStatusExp / invoke ile çağrılabilir:

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

O zaman aşağıdaki gibi kullanın:

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

Veya sınıfta sorgulama TotalPhysicalMemoryyapmak için WMI (yönetilen ancak daha yavaş) kullanabilirsiniz Win32_ComputerSystem.


2
Bu işe yaramıyor ... long ramuse = (long) stat.TotalPhysical; long ramavailable = (long) stat.AvailablePhysical; uzun ramtotal = kullanılabilir + yaygın; int yüzde = (int) ((float) ramuse / ramtotal * 100); yüzde bana "70" diyor ve toplam sürekli değişiyor, 100 ver ya da al.% 72 olmalı
Joel

5
Kod çalışır, yalnızca nesnenin boyutunu elde etmek için 'NativeMethods' kullanmanız gerekmez, basitçe şöyle söyleyebilirsiniz: this.dwLength = (uint)Marshal.SizeOf(this);ve aynı şekilde çalışıyor (NativeMethods kullanırken sorun yaşadığım için bu düzeltme şimdi çalışıyor).
Cipi

2
"NativeMethods", türün ad alanıdır. SizeOf çağrısı tercih ederseniz değiştirilebilir.
Philip Rieck

2
@Corelgott Güncel bilgiler verdiği için işe yaramıyor mu? Demek istediğim, hava durumu kanalını her kontrol ettiğimde farklı bilgiler veriyor, ama tamamen yararsız diyecek kadar ileri gitmem. Her seferinde potansiyel olarak farklı bilgiler döndürmeseydi, bu işlevin ne yapmasını istediğinizden bile emin değilim - ilk çalıştırmadan sonra sonuçları "kilitlemeli" ve ardından eski verileri döndürmeli mi? Bu ne şekilde daha yararlı olur?
Philip Rieck

2
Partiye biraz geç kaldım ama ben bu konuya girdim ve bu cevap doğru değil. GlobalMemoryStatusEx, makineye kurulu gerçek RAM miktarını zorunlu olarak vermez (ve çoğu zaman vermez), işletim sistemi için mevcut olan ve sürücüler için ayrılmış bellek nedeniyle kurulu miktardan neredeyse her zaman farklı olan miktarı verir. Yüklü RAM miktarını almak için, uygun toplam RAM'i döndüren GetPhysicallyInstalledSystemMemory işlevini çağırmak isteyebilirsiniz. msdn.microsoft.com/en-us/library/windows/desktop/…
Mike Johnson

183

Bir referans ekleyin Microsoft.VisualBasicve a using Microsoft.VisualBasic.Devices;.

ComputerInfoSınıf ihtiyacınız tüm bilgileri alır.


10
Bu neden reddedildi? Tekrar oy verildi! Bunu yapmanın en kolay yolu budur ve evet bunu C # 'dan yapabilirsiniz.
Paul Batum

54
+1: Bazı insanlar Microsoft.VisualBasic ad alanına C # dan başvurmaktan hoşlanmazlar, gerçi gerçekten her şeyin bir parçası olarak kurulan başka bir derleme.
Bevan

2
8gb ram ile Windows7 64bit üzerinde negatif önemsiz değer döndürür. Bu yüzden oy aldın mı?
Piotr Kula

6
(New ComputerInfo ()). TotalPhysicalMemory kullanmaktan çekinen herkes için, bundan daha fazla belleğe sahip bir sistemde sorunsuz çalışır. Dönüş türü işaretsiz uzun, bu nedenle (geçersiz) bir atama olmadan negatif bir sayı mümkün değildir.
Miles Strombach

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

63

Yukarıda belirtildiği gibi Microsoft.VisualBasic.dll için bir başvuru ekleyin. O zaman toplam fiziksel belleği elde etmek bu kadar basit (evet, test ettim):

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

4
@ppumkin, .NET'in hangi sürümünde ve Visual Studio'nun hangi sürümünde? 8 GB RAM ile 64 bitlik bir makinede .NET 4.5 kullanarak VS 2012'de çalıştırdığımda iyi çalışıyor. 8520327168'i geri alıyorum.
Ryan Lundy 13

.NET 4, Windows Pro 7 64bit üzerinde VS2010 32bit
Piotr Kula

2
X64'te iyi çalışıyor. 32 bitlik bir VS kullanıyorsunuz ve bu muhtemelen tam bellek boyutunu görmeyecek 32 bit ikili dosyalar derliyor.
Lucas Teske

2
Bunu Visual Studio 2017'de C # .Net 4.6.1 ile kullanırken, bunun işe yaraması için Microsoft.VisualBasic'e bir referans eklemem gerekiyordu. Proje> Referans Ekle >> Montajlar> Microsoft.VisualBasic'i Kontrol Edin >> Tamam
WebLuke

GetPhysicallyInstalledSystemMemory ve Microsoft.VisualBasic.Devices.ComputerInfo () arasında bir fark fark ettim. TotalPhysicalMemory new FileSizeStruct (34173231104) {31.8 GB} ByteCount: 34173231104 ByteSize: GB ByteSizeStruct: 3297 ByteSizeStruct (343597ByteSizeStruct) {343597 GB Boyutu: 32
fanuc_bob

36

Kabul dahil olmak üzere buraya Bütün cevaplar, size toplam RAM miktarını verecektir mevcut kullanım için. Ve bu OP'nin istediği şey olabilir.

Ancak, yüklü RAM miktarını almakla ilgileniyorsanız , GetPhysicallyInstalledSystemMemory işlevine bir çağrı yapmak isteyeceksiniz .

Bağlantıdan Açıklamalar bölümünde:

GetPhysicallyInstalledSystemMemory fonksiyon bilgisayarın SMBIOS firmware tablolardan fiziksel olarak yüklü RAM miktarını alır. Bu , MEMORYSTATUSEX yapısının ullTotalPhys üyesini işletim sisteminin kullanabileceği fiziksel bellek miktarına ayarlayan GlobalMemoryStatusEx işlevi tarafından bildirilen miktardan farklı olabilir . BIOS ve bazı sürücüler, bellek eşlemeli aygıtlar için G / Ç bölgeleri olarak bellek ayırabileceğinden, işletim sistemi tarafından kullanılabilen bellek miktarı, bilgisayara fiziksel olarak yüklenmiş bellek miktarından daha az olabilir, bu da belleği işletim sistemi için kullanılamaz hale getirir. ve uygulamalar.

Basit kod:

[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
Teşekkür ederim! Ben tam olarak bunu arıyordum ama her yerde sadece kurulu olanı değil toplam kullanılabilir belleği nasıl bulacağımı görebiliyorum.
SM

Ana makinede mükemmel çalışmasına rağmen, sanal makinemde iyi çalışmıyor.
SM

31

Mono kullanıyorsanız, Mono 2.8'in (bu yıl sonra piyasaya sürülecek), Mono'nun çalıştığı tüm platformlarda (Windows dahil) fiziksel bellek boyutunu bildiren bir performans sayacına sahip olacağını bilmek ilginizi çekebilir. Bu kod parçacığını kullanarak sayacın değerini alırsınız:

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

Performans sayacını sağlayan C koduyla ilgileniyorsanız, burada bulunabilir .


ARM sistemlerinde bile herhangi bir linux sisteminde iyi çalışır.
harry4516

@ Ubuntu sistemimde harry4516, PerformanceCounter desteklenmiyor
Carlos Liu

14

Bunu yapmanın başka bir yolu da .NET System.Management sorgulama olanaklarını kullanmaktır:

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;

Bu, makinemde bir System.Management.ManagementException Out of Memory atıyor. Herhangi bir fikir?
Amar

2
Bunu beğendim. Referans vermeye gerek yok Microsoft.VisualBasic.Devices. Ve tek astar olarakvar Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
VDWWD

10

Kullananlar için mevcut fiziksel hafızayı elde etmek için platform .net Core 3.0kullanmaya gerek yoktur PInvoke. GCSınıf yeni bir yöntem eklendi GC.GetGCMemoryInfobir döner GCMemoryInfo Structile TotalAvailableMemoryBytesbir özelliği olarak gerçekleştirilebilir. Bu özellik, çöp toplayıcı için toplam kullanılabilir belleği döndürür. (MEMORYSTATUSEX ile aynı değer)

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

En sevdiğim cevap. Teşekkürler.
Matas Vaitkevicius

7

bu bilgileri almak için bu kodu kullanabilirsiniz, sadece referansı ekleyin

using Microsoft.VisualBasic.Devices;

ve basitçe aşağıdaki kodu kullanın

    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 sürümünde bulunamadı. Demek istediğim ComputerInfo ad alanı bulunamadı. hatta daha fazlası ... ad alanı 'Cihazlar' mevcut değil.
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 kullanabilirsiniz. Snippit buldum.

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

Bunu not et SetArtık VB.NET için gerekli olmadığını , bu VB6 kodu mu?
jrh

2

Bu işlev ( ManagementQuery) Windows XP ve sonraki sürümlerde çalışır:

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

Kullanım:

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

2
bu BytesToMbişlev nereden geliyor?
Cee McSharpface

@dlatikay bu içsel işlev: özel statik çift BytesToMb (uzun bayt) {dönüş Math.Round (bayt / 1024d / 1024d, 2); }
Lance

1

.Net ve Mono ile uyumlu (Win10 / FreeBSD / CentOS ile test edilmiştir)

Kullanılması ComputerInfokaynak kodunu ve PerformanceCounterMono ve Net için yedek olarak s:

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

Henüz kimse GetPerformanceInfo'dan bahsetmedi . PInvoke imzaları mevcuttur.

Bu işlev, sistem genelinde aşağıdaki bilgileri kullanılabilir hale getirir:

  • CommitTotal
  • CommitLimit
  • CommitPeak
  • Fiziksel Toplam
  • Fiziksel Kullanılabilir
  • Sistem Önbelleği
  • Çekirdek Toplamı
  • KernelPaged
  • KernelNonpaged
  • Sayfa boyutu
  • Tutamak
  • ProcessCount
  • ThreadCount

PhysicalTotalDeğer sayfa sayısı olmasına rağmen, OP'nin aradığı şeydir, bu nedenle bayta dönüştürmek için PageSizedöndürülen değerle çarpın .


0

.NIT'in toplam erişebileceği bellek miktarı için bir sınırı vardır. Bir yüzde var ve sonra xp'de 2 GB sert tavan oldu.

İçinde 4 GB olabilir ve 2 GB'a ulaştığında uygulamayı öldürebilir.

Ayrıca 64 bit modunda, sistem dışında kullanabileceğiniz bir bellek yüzdesi vardır, bu yüzden her şeyi isteyip isteyemeyeceğinizden veya bunun özellikle korunup korunmadığından emin değilim.


/Hayır/. Toplam fiziksel bellek, fiziksel olarak yüklenmiş gerçek bellek anlamına gelir.
Matthew Flaschen

Aslında, DevelopingChris doğrudur. 4 Gig Ram'li bir XP makinesinde GlobalMemoryStatusEx'i ararsanız, yalnızca 3 Gig kurulu olduğunu bildirecektir.
epotter

Ayrıca, Win32_ComputerSystem veya Win32_LogicalMemoryConfiguration'da TotalPhysicalMemory'yi sorgulamak için WMI kullanılması da yanlış sonuç verir.
epotter

teşekkür ederim, soruyu anlamadığımdan değil, bilgi için .net kitaplığı dışında farklı bir kaynak kullanmanız gerektiğidir.
DevelopingChris

Bu cevap, mantıklı olan tek cevaptır. Referans verilen VisualBasic'i kullanarak Win 64 8Gb ram üzerinde yoruldum. Önemsiz negatif değerler alıyorum.
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
Bu, çevrimiçi Visual Basic'ten CShap'e dönüştürücüler sayesinde olabilir.
Nick Binnet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.