Comment obtenir la quantité totale de RAM de l'ordinateur?

88

En utilisant C #, je souhaite obtenir la quantité totale de RAM dont dispose mon ordinateur. Avec le PerformanceCounter, je peux obtenir la quantité de RAM disponible, en définissant:

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

Mais je n'arrive pas à trouver un moyen d'obtenir la quantité totale de mémoire. Comment pourrais-je procéder?

Mise à jour:

MagicKat: J'ai vu ça quand je cherchais, mais ça ne marche pas - "Vous manquez un assemblage ou une référence?". J'ai cherché à ajouter cela aux références, mais je ne le vois pas.

Joël
la source

Réponses:

62

La fonction API Windows GlobalMemoryStatusExpeut être appelée avec 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);

Ensuite, utilisez comme:

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

Ou vous pouvez utiliser WMI (géré mais plus lent) pour interroger TotalPhysicalMemoryla Win32_ComputerSystemclasse.

Philip Rieck
la source
2
Cela ne fonctionne pas ... long ramuse = (long) stat.TotalPhysical; long ramavailable = (long) stat.AvailablePhysical; long ramtotal = ramavailable + ramuse; int pour cent = (int) ((float) ramuse / ramtotal * 100); pour cent me dit "70" et le total change constamment, donnez ou prenez 100. devrait être 72%
Joel
5
Le code fonctionne, seulement vous n'avez pas besoin d'utiliser 'NativeMethods' pour obtenir la taille de l'objet, vous pouvez simplement dire comme ceci: this.dwLength = (uint)Marshal.SizeOf(this);et cela fonctionne de la même manière (j'ai eu des problèmes avec l'utilisation de NativeMethods donc ce correctif fonctionne maintenant).
Cipi le
2
"NativeMethods" est l'espace de noms du type. L'appel à SizeOf peut être modifié si vous préférez.
Philip Rieck
2
@Corelgott Inutile parce qu'il donne des informations à jour? Je veux dire, chaque fois que je regarde la chaîne météo, cela donne des informations différentes, mais je n'irais pas jusqu'à dire que cela est totalement inutile. Je ne suis même pas sûr de ce que vous voudriez que cette fonction fasse si elle ne retournait pas des informations potentiellement différentes à chaque fois - devrait-elle "verrouiller" les résultats après le premier appel, puis renvoyer des données périmées après cela? En quoi cela serait-il plus utile?
Philip Rieck
2
Un peu tard à la fête mais je suis tombé sur ce fil et cette réponse n'est pas correcte. GlobalMemoryStatusEx ne donne pas nécessairement (et souvent ne donnera pas) la quantité réelle de RAM installée sur la machine, il donne la quantité disponible pour le système d'exploitation qui est presque toujours différente de la quantité installée en raison de la mémoire réservée aux pilotes, etc. Pour obtenir la quantité réelle de RAM installée, vous voudrez appeler la fonction GetPhysicallyInstalledSystemMemory qui renvoie la RAM totale appropriée. msdn.microsoft.com/en-us/library/windows/desktop/…
Mike Johnson
182

Ajoutez une référence à Microsoft.VisualBasicet a using Microsoft.VisualBasic.Devices;.

La ComputerInfoclasse a toutes les informations dont vous avez besoin.

MagicKat
la source
10
Pourquoi diable a-t-il été rejeté? Voté de nouveau! C'est le moyen le plus simple de le faire, et oui, vous pouvez cela à partir de C #.
Paul Batum
54
+1: Certaines personnes ont une aversion pour faire référence à l'espace de noms Microsoft.VisualBasic à partir de C #, même s'il ne s'agit en réalité que d'un autre assembly installé dans le cadre de tout le reste.
Bevan
2
Renvoie une valeur indésirable négative sur Windows7 64 bits avec 8 Go de RAM. C'est pourquoi vous avez voté?
Piotr Kula
6
Pour quiconque se méfie d'utiliser (new ComputerInfo ()). TotalPhysicalMemory, cela fonctionne bien sur un système avec encore plus de mémoire que cela. Son type de retour est unsigned long, donc un nombre négatif n'est pas possible sans un cast (invalide).
Miles Strombach du
6
var totalGBRam = Convert.ToInt32 ((new ComputerInfo (). TotalPhysicalMemory / (Math.Pow (1024, 3))) + 0,5);
Sean
63

Ajoutez une référence à Microsoft.VisualBasic.dll, comme mentionné ci-dessus. Ensuite, obtenir la mémoire physique totale est aussi simple que cela (oui, je l'ai testé):

static ulong GetTotalMemoryInBytes()
{
    return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
}
Ryan Lundy
la source
4
@ppumkin, dans quelle version de .NET et dans quelle version de Visual Studio? Lorsque je l'exécute dans VS 2012 en utilisant .NET 4.5 sur une machine 64 bits avec 8 Go de RAM, cela fonctionne bien. Je reviens 8520327168.
Ryan Lundy
.NET 4, VS2010 32 bits sur Windows Pro 7 64 bits
Piotr Kula
2
Fonctionne très bien sur x64.Vous utilisez un VS 32 bits qui compile probablement des binaires 32 bits qui ne verront pas la pleine taille de la mémoire.
Lucas Teske
2
Lors de l'utilisation de cela dans Visual Studio 2017 avec C # .Net 4.6.1, j'ai dû ajouter une référence pour Microsoft.VisualBasic pour que cela fonctionne. Projet> Ajouter une référence >> Assemblies> Vérifier Microsoft.VisualBasic >> OK
WebLuke
J'ai remarqué une différence entre GetPhysicallyInstalledSystemMemory et Microsoft.VisualBasic.Devices.ComputerInfo (). GB Size: 32
fanuc_bob
36

Toutes les réponses ici, y compris celle acceptée, vous donneront la quantité totale de RAM disponible . Et c'est peut-être ce que voulait OP.

Mais si vous souhaitez obtenir la quantité de RAM installée , vous voudrez passer un appel au GetPhysicallyInstalledSystemMemory fonction .

À partir du lien, dans la section Remarques:

La fonction GetPhysicallyInstalledSystemMemory récupère la quantité de RAM physiquement installée à partir des tables de microprogramme SMBIOS de l'ordinateur. Cela peut différer de la quantité signalée par la fonction GlobalMemoryStatusEx , qui définit le membre ullTotalPhys de la structure MEMORYSTATUSEX sur la quantité de mémoire physique disponible pour le système d'exploitation à utiliser. La quantité de mémoire disponible pour le système d'exploitation peut être inférieure à la quantité de mémoire physiquement installée sur l'ordinateur car le BIOS et certains pilotes peuvent réserver de la mémoire en tant que régions d'E / S pour les périphériques mappés en mémoire, rendant la mémoire indisponible pour le système d'exploitation et applications.

Exemple de code:

[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
la source
1
Merci! Je cherchais exactement cela mais partout je ne peux voir que comment trouver la mémoire totale disponible plutôt que celle installée.
SM du
Cela ne fonctionne pas bien sur ma machine virtuelle, même si elle fonctionne parfaitement sur la machine principale.
SM du
31

Si vous utilisez Mono, vous serez peut-être intéressé de savoir que Mono 2.8 (qui sortira plus tard cette année) aura un compteur de performances qui indique la taille de la mémoire physique sur toutes les plates-formes sur lesquelles Mono fonctionne (y compris Windows). Vous récupéreriez la valeur du compteur à l'aide de cet extrait de code:

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

Si vous êtes intéressé par le code C qui fournit le compteur de performance, il peut être trouvé ici .

Grendel
la source
fonctionne très bien sur n'importe quel système Linux, même sur les systèmes ARM.
harry4516
14

Une autre façon de procéder consiste à utiliser les fonctionnalités d'interrogation .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;
zgerd
la source
Cela lance une exception System.Management.ManagementException de mémoire insuffisante sur ma machine. Des idées?
Amar
2
J'aime celui la. Pas besoin de référence Microsoft.VisualBasic.Devices. Et comme one-linervar Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
VDWWD
10

Pour ceux qui utilisent, .net Core 3.0il n'est pas nécessaire d'utiliser la PInvokeplate-forme pour obtenir la mémoire physique disponible. La GCclasse a ajouté une nouvelle méthode GC.GetGCMemoryInfoqui renvoie un GCMemoryInfo Structwith TotalAvailableMemoryBytescomme propriété. Cette propriété renvoie la mémoire totale disponible pour le garbage collector. (Même valeur que 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
la source
Ma réponse préférée. Merci.
Matas Vaitkevicius
7

vous pouvez simplement utiliser ce code pour obtenir ces informations, ajoutez simplement la référence

using Microsoft.VisualBasic.Devices;

et utilisez simplement le code suivant

    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
la source
introuvable dans la version .net 4.6. Je veux dire qu'il donne l'espace de noms ComputerInfo est introuvable. encore plus ... l'espace de noms «Périphériques» n'existe pas.
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
la source
5

Vous pouvez utiliser WMI. Vous avez trouvé un extrait.

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
la source
Notez que ce Setn'est plus nécessaire pour VB.NET, est-ce le code VB6?
jrh
2

Cette fonction ( ManagementQuery) fonctionne sur Windows XP et versions ultérieures:

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

Usage:

Console.WriteLine(BytesToMb(Convert.ToInt64(ManagementQuery("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem", "TotalPhysicalMemory", "root\\CIMV2"))));
Lance
la source
2
d'où vient cette BytesToMbfonction?
Cee McSharpface
@dlatikay c'est une fonction interne: double statique privé BytesToMb (longs octets) {return Math.Round (bytes / 1024d / 1024d, 2); }
Lance le
1

Compatible avec .Net et Mono (testé avec Win10 / FreeBSD / CentOS)

Utilisation ComputerInfodu code source et des PerformanceCounters pour Mono et comme sauvegarde pour .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
la source
0

Personne n'a encore mentionné GetPerformanceInfo . Les signatures PInvoke sont disponibles.

Cette fonction rend disponibles les informations suivantes à l'échelle du système:

  • CommitTotal
  • CommitLimit
  • CommitPeak
  • PhysiqueTotal
  • Physique Disponible
  • SystemCache
  • KernelTotal
  • KernelPaged
  • KernelNon paginé
  • Taille de la page
  • HandleCount
  • ProcessCount
  • ThreadCount

PhysicalTotalest ce que l'OP recherche, bien que la valeur soit le nombre de pages, donc pour convertir en octets, multipliez par la PageSizevaleur retournée.

Roman Starkov
la source
0

.NIT a une limite à la quantité de mémoire à laquelle il peut accéder par rapport au total. Theres un pourcentage, puis 2 Go en xp était le plafond dur.

Vous pourriez avoir 4 Go dedans, et cela tuerait l'application quand elle atteindrait 2 Go.

Toujours en mode 64 bits, il y a un pourcentage de mémoire que vous pouvez utiliser hors du système, donc je ne suis pas sûr si vous pouvez demander le tout ou si cela est spécifiquement protégé.

DévelopperChris
la source
/Non/. La mémoire physique totale désigne la mémoire réellement installée physiquement.
Matthew Flaschen
En fait, DevelopingChris est correct. Si vous appelez GlobalMemoryStatusEx sur une machine XP avec 4 Go de RAM, il signalera qu'il n'y a que 3 Go installés.
epotter
En outre, l'utilisation de WMI pour interroger TotalPhysicalMemory dans Win32_ComputerSystem ou Win32_LogicalMemoryConfiguration produit également un résultat incorrect.
epotter
merci, ce n'est pas que je ne comprends pas la question, c'est que vous devez utiliser une source différente pour les informations autre qu'une bibliothèque .net.
DevelopingChris
Cette réponse est la seule qui ait du sens. Je l'ai fatigué maintenant sur Win 64 8 Go de RAM en utilisant VisualBasic référencé. J'obtiens des valeurs négatives indésirables.
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
la source
6
Cela pourrait être dû aux convertisseurs en ligne Visual Basic vers CShap.
Nick Binnet