コンピュータに搭載されているRAMの総量をどのように取得しますか?


89

C#を使用して、コンピューターに搭載されているRAMの合計量を取得したいと思います。PerformanceCounterを使用すると、次のように設定することで、使用可能なRAMの量を取得できます。

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

しかし、メモリの総量を取得する方法を見つけることができないようです。どうすればこれを行うことができますか?

更新:

MagicKat:検索中にそれを見ましたが、機能しません-「アセンブリまたは参照がありませんか?」。それをリファレンスに追加しようとしましたが、そこには表示されません。

回答:


63

Windows API関数GlobalMemoryStatusExは、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);

次に、次のように使用します。

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

または、WMI(管理対象ですが低速)を使用TotalPhysicalMemoryしてWin32_ComputerSystemクラスでクエリを実行できます。


2
それは機能していません... long ramuse =(long)stat.TotalPhysical; long ramavailable =(long)stat.AvailablePhysical; long ramtotal = ramavailable + ramuse; intパーセント=(int)((float)ramuse / ramtotal * 100); パーセントは私に「70」と言っており、合計は絶えず変化しています。100を与えるか取るか。72%である必要があります
Joel

5
コードは機能します。オブジェクトのサイズを取得するために「NativeMethods」を使用する必要はありません。次のように言うことができます。同じようthis.dwLength = (uint)Marshal.SizeOf(this);に機能します(NativeMethodsの使用に問題があったため、この修正が機能するようになりました)。
Cipi 2010

2
「NativeMethods」は、タイプの名前空間です。必要に応じて、SizeOfの呼び出しを変更できます。
フィリップリーク2010

2
@Corelgott最新の情報を提供するので役に立たない?つまり、天気予報チャンネルをチェックするたびに、さまざまな情報が得られますが、まったく役に立たないとは言えません。毎回異なる可能性のある情報を返さない場合、この関数で何をしたいかさえわかりません。最初の呼び出し後に結果を「ロック」し、その後に古いデータを返す必要がありますか?それはどのようにもっと役立つでしょうか?
フィリップリーク2013年

2
パーティーに少し遅れましたが、私はこのスレッドに遭遇し、この答えは正しくありません。GlobalMemoryStatusExは、マシンにインストールされているRAMの実際の量を必ずしも提供しません(多くの場合、提供しません)。OSで使用可能な量を提供します。これは、ドライバー用に予約されたメモリなどのためにインストールされている量とはほとんど常に異なります。 。インストールされているRAMの実際の量を取得するには、適切な合計RAMを返すGetPhysicallyInstalledSystemMemory関数を呼び出す必要があります。msdn.microsoft.com/en-us/library/windows/desktop/…–
Mike Johnson

183

Microsoft.VisualBasicとへの参照を追加しますusing Microsoft.VisualBasic.Devices;

ComputerInfoクラスはあなたが必要とするすべての情報を持っています。


10
一体なぜこれが投票されなかったのですか?反対票を投じました!これはそれを行う最も簡単な方法であり、そうです、C#からこれを行うことができます。
Paul Batum

54
+1:C#からMicrosoft.VisualBasic名前空間を参照することに嫌悪感を抱く人もいますが、それは実際には他のすべての一部としてインストールされる単なる別のアセンブリです。
Bevan

2
8GBのRAMを搭載したWindows764ビットで負のジャンク値を返します。だからあなたは投票を取り下げたのですか?
ピオトルクラ2012

6
(new ComputerInfo())。TotalPhysicalMemoryを使用することに嫌気がさしている人にとっては、それよりもさらに多くのメモリを備えたシステムで正常に動作します。その戻り値の型はunsignedlongであるため、(無効な)キャストなしでは負の数は使用できません。
マイルストロンバッハ2015

6
var totalGBRam = Convert.ToInt32((new ComputerInfo()。TotalPhysicalMemory /(Math.Pow(1024、3)))+ 0.5);
ショーン

63

上記の誰かのように、Microsoft.VisualBasic.dllへの参照を追加します。次に、合計物理メモリを取得するのはこれと同じくらい簡単です(はい、私はそれをテストしました):

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

4
@ ppumkin、.NETのどのバージョン、およびVisual Studioのどのバージョンで?8GBのRAMを搭載した64ビットマシンで.NET4.5を使用してVS2012で実行すると、正常に動作します。私は8520327168を取り戻します。–
Ryan Lundy

.NET 4、VS2010 32ビット(Windows Pro 7 64ビット)
Piotr Kula

2
x64で正常に動作します。32ビットVSを使用しており、おそらくフルメモリサイズが表示されない32ビットバイナリをコンパイルしています。
Lucas Teske 2014

2
Visual Studio2017でC#.Net 4.6.1を使用してこれを使用する場合、これを機能させるには、Microsoft.VisualBasicの参照を追加する必要がありました。プロジェクト>参照の追加>>アセンブリ> Microsoft.VisualBasicの確認>> OK
WebLuke 2018年

GetPhysicallyInstalledSystemMemoryとMicrosoft.VisualBasic.Devices.ComputerInfo()。TotalPhysicalMemoryの違いに気づきました。newFileSizeStruct(34173231104){31.8 GB} ByteCount:34173231104 ByteSize:GB Size:31.8 new FileSizeStruct(34359738368){32 GB} ByteCount:34359738368 Byte GBサイズ:32
fanuc_bob 2018年

36

受け入れられたものを含むここでのすべての答えは、使用可能なRAMの合計量を示します。そしてそれがOPが望んでいたことだったのかもしれません。

ただし、インストールされているRAMの量を取得することに関心がある場合は、GetPhysicallyInstalledSystemMemory関数を呼び出す必要があります。

リンクから、備考セクションで:

GetPhysicallyInstalledSystemMemory機能は、コンピュータのSMBIOSファームウェアのテーブルから物理的にインストールされているRAMの量を取得します。これは、MEMORYSTATUSEX構造体のullTotalPhysメンバーをオペレーティングシステムが使用できる物理メモリの量に設定するGlobalMemoryStatusEx関数によって報告される量とは異なる場合があります。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.");
}

1
ありがとうございました!私はまさにこれを探していましたが、どこでも、インストールされているメモリではなく、使用可能なメモリの合計を見つける方法しかわかりません。
SM

メインの仮想マシンでは完全に機能しているにもかかわらず、私の仮想マシンではうまく機能しません。
SM

31

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コードに興味がある場合は、ここにあります


ARMシステムでも、どのLinuxシステムでも正常に動作します。
harry4516 2017年

@ harry4516私のUbuntuシステム上、PerformanceCounterはサポートされていません
カルロス・劉

14

これを行う別の方法は、.NETSystem.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;

これにより、System.Management.ManagementExceptionがマシンのメモリ不足になります。何か案は?
アマール

2
私はこれが好きです。参照する必要はありませんMicrosoft.VisualBasic.Devices。そして、ワンライナーとしてvar Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
VDWWD

10

使用している人にとっては、利用可能な物理メモリを取得するためにプラットフォーム.net Core 3.0を使用する必要はありませんPInvoke。このGCクラスにはGC.GetGCMemoryInfoGCMemoryInfo StructwithTotalAvailableMemoryBytesをプロパティとして返す新しいメソッドが追加されています。このプロパティは、ガベージコレクターに使用可能な合計メモリを返します(MEMORYSTATUSEXと同じ値)

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

私の好きな答え。ありがとう。
MatasVaitkevicius20年

7

このコードを使用してこれらの情報を取得するだけで、参照を追加するだけです

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

.net4.6バージョンにはありません。ComputerInfo名前空間が見つからないことを意味します。さらに...名前空間 'デバイス'は存在しません。
グムル

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を使用できます。スニピットを見つけました。

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

SetVB.NETでは不要になったことに注意してください。これはVB6コードですか?
jrh 2017年

2

この関数(ManagementQuery)は、WindowsXP以降で機能します。

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

2
そのBytesToMb機能はどこから来たのですか?
Cee McSharpface 2017年

@dlatikayそれは内部関数です:private static double BytesToMb(long bytes){return Math.Round(bytes / 1024d / 1024d、2); }
ランス

1

.NetおよびMonoと互換性があります(Win10 / FreeBSD / CentOSでテスト済み)

MonoのComputerInfoソースコードとPerformanceCountersを使用し、.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

GetPerformanceInfoについてはまだ誰も言及していません。PInvoke署名が利用可能です。

この機能により、次のシステム全体の情報が利用可能になります。

  • CommitTotal
  • CommitLimit
  • CommitPeak
  • PhysicalTotal
  • PhysicalAvailable
  • SystemCache
  • KernelTotal
  • KernelPaged
  • KernelNonpaged
  • ページサイズ
  • HandleCount
  • ProcessCount
  • スレッド数

PhysicalTotal値はページ数ですが、OPが探しているものです。したがって、バイトに変換するには、PageSize返された値を掛けます。


0

.NITには、合計でアクセスできるメモリの量に制限があります。パーセンテージがあり、xpの2GBが厳しい上限でした。

4 GBを含めることができ、2GBに達するとアプリが強制終了されます。

また、64ビットモードでは、システムから使用できるメモリの割合があるため、すべてを要求できるかどうか、またはこれが特に保護されているかどうかはわかりません。


/番号/。総物理メモリとは、物理的にインストールされている実際のメモリを意味します。
Matthew Flaschen 2009年

実際、DevelopingChrisは正しいです。4ギガのRAMを搭載したXPマシンでGlobalMemoryStatusExを呼び出すと、3ギガしかインストールされていないことが報告されます。
epotter 2009

また、WMIを使用してWin32_ComputerSystemまたはWin32_LogicalMemoryConfigurationのTotalPhysicalMemoryをクエリすると、間違った結果が生成されます。
epotter 2009

ありがとうございます。.netライブラリ以外の情報に別のソースを使用する必要があるという質問が理解できないわけではありません。
DevelopingChris

この答えは理にかなっている唯一のものです。参照されているVisualBasicを使用して、Win 648GbRAMで疲れました。がらくたの負の値を取得します。
ピオトルクラ2012

-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
これは、オンラインのVisualBasicからCShapへのコンバーターのおかげかもしれません。
Nick Binnet 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.