Как вы получаете общий объем оперативной памяти компьютера?
Используя C#, я хочу получить общий объем оперативной памяти, который есть на моем компьютере. С PerformanceCounter я могу получить количество доступных оперативной памяти, установив:
counter.CategoryName = "Memory";
counter.Countername = "Available MBytes";
Но я не могу найти способ получить общий объем памяти. Как бы я поступил так?
Обновить:
MagicKat: Я видел это, когда искал, но это не работает - "Вы пропустили сборку или ссылку?". Я смотрел, чтобы добавить это в список литературы, но я не вижу там.
18 ответов
Способ p/invoke РЕДАКТИРОВАТЬ: изменен на GlobalMemoryStatusEx для получения точных результатов (хе)
[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".
Изменить фиксированный код для комментария от joel-llamaduck.blogspot.com
Добавить ссылку на Microsoft.VisualBasic
и using Microsoft.VisualBasic.Devices;
,
ComputerInfo
В классе есть вся информация, которая вам нужна.
Добавьте ссылку на Microsoft.VisualBasic.dll, как кто-то упоминал выше. Тогда получить полную физическую память так же просто (да, я проверял это):
static ulong GetTotalMemoryInBytes()
{
return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
}
Все ответы, включая принятые, дадут вам общий объем оперативной памяти, доступной для использования. И это, возможно, было то, что хотел ОП.
Но если вы заинтересованы в том, чтобы получить объем установленной оперативной памяти, вам нужно будет вызвать функцию GetPhysicallyInstalledSystemMemory.
По ссылке, в разделе "Замечания":
Функция GetPhysicallyInstalledSystemMemory извлекает объем физически установленной оперативной памяти из таблиц микропрограммного обеспечения компьютера SMBIOS. Это может отличаться от объема, сообщаемого функцией GlobalMemoryStatusEx, которая устанавливает для члена ullTotalPhys структуры MEMORYSTATUSEX объем физической памяти, доступной для используемой операционной системы. Объем памяти, доступный операционной системе, может быть меньше объема памяти, физически установленного на компьютере, поскольку BIOS и некоторые драйверы могут резервировать память в качестве областей ввода-вывода для устройств с отображенной памятью, что делает память недоступной для операционной системы. и приложения.
Образец кода:
[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.");
}
Для тех, кто использует .net Core 3.0
нет необходимости использовать PInvoke
платформу, чтобы получить доступную физическую память. ВGC
класс добавил новый метод GC.GetGCMemoryInfo
что возвращает GCMemoryInfo Struct
с TotalAvailableMemoryBytes
как собственность. Это свойство возвращает общий объем доступной памяти для сборщика мусора (то же значение, что и MEMORYSTATUSEX).
var gcMemoryInfo = GC.GetGCMemoryInfo();
installedMemory = gcMemoryInfo.TotalAvailableMemoryBytes;
// it will give the size of memory in MB
var physicalMemory = (double) installedMemory / 1048576.0;
Если вы используете 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-коде, который предоставляет счетчик производительности, его можно найти здесь.
Другой способ сделать это - использовать средства запросов.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;
Вы можете просто использовать этот код, чтобы получить эту информацию, просто добавьте ссылку
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();
}
// 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";
}
Вы могли бы использовать 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
Решение работает на Linux (.Net Core) . Вдохновлено GitHub/Hardware.Info . Оптимизирован для минимального выделения памяти, а среднее извлечение занимает 0,020 мс.
private static readonly object _linuxMemoryLock = new();
private static readonly char[] _arrayForMemInfoRead = new char[200];
public static void GetBytesCountOnLinux(out ulong availableBytes, out ulong totalBytes)
{
lock (_linuxMemoryLock) // lock because of reusing static fields due to optimization
{
totalBytes = GetBytesCountFromLinuxMemInfo(token: "MemTotal:", refreshFromFile: true);
availableBytes = GetBytesCountFromLinuxMemInfo(token: "MemAvailable:", refreshFromFile: false);
}
}
private static ulong GetBytesCountFromLinuxMemInfo(string token, bool refreshFromFile)
{
// NOTE: Using the linux file /proc/meminfo which is refreshed frequently and starts with:
//MemTotal: 7837208 kB
//MemFree: 190612 kB
//MemAvailable: 5657580 kB
var readSpan = _arrayForMemInfoRead.AsSpan();
if (refreshFromFile)
{
using var fileStream = new FileStream("/proc/meminfo", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var reader = new StreamReader(fileStream, Encoding.UTF8, leaveOpen: true);
reader.ReadBlock(readSpan);
}
var tokenIndex = readSpan.IndexOf(token);
var fromTokenSpan = readSpan.Slice(tokenIndex + token.Length);
var kbIndex = fromTokenSpan.IndexOf("kB");
var notTrimmedSpan = fromTokenSpan.Slice(0, kbIndex);
var trimmedSpan = notTrimmedSpan.Trim(' ');
var kBytesCount = ulong.Parse(trimmedSpan);
var bytesCount = kBytesCount * 1024;
return bytesCount;
}
Linux и Windows вместе — для простого копирования и вставки. Код Windows взят из принятого ответа .
public static void GetRamBytes(out ulong availableBytes, out ulong totalBytes)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
GetBytesCountOnLinux(out availableBytes, out totalBytes);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
GetBytesCountOnWindows(out availableBytes, out totalBytes);
}
else
{
throw new NotImplementedException("Not implemented for OS: " + Environment.OSVersion);
}
}
private static readonly object _winMemoryLock = new();
private static readonly MEMORYSTATUSEX _memStatus = new();
private static void GetBytesCountOnWindows(out ulong availableBytes, out ulong totalBytes)
{
lock (_winMemoryLock) // lock because of reusing the static class _memStatus
{
GlobalMemoryStatusEx(_memStatus);
availableBytes = _memStatus.ullAvailPhys;
totalBytes = _memStatus.ullTotalPhys;
}
}
[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(MEMORYSTATUSEX));
}
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GlobalMemoryStatusEx([In] [Out] MEMORYSTATUSEX lpBuffer);
Совместим с.Net и Mono (протестировано с Win10/FreeBSD/CentOS)
С помощью ComputerInfo
исходный код и PerformanceCounter
s для Mono и в качестве резервной копии для.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)))
};
}
}
}
Эта функция (ManagementQuery
) работает на Windows XP и более поздних версиях:
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"))));
Никто еще не упомянул GetPerformanceInfo. PInvoke подписи доступны.
Эта функция делает доступной следующую общесистемную информацию:
- CommitTotal
- CommitLimit
- CommitPeak
- PhysicalTotal
- PhysicalAvailable
- SystemCache
- KernelTotal
- KernelPaged
- KernelNonpaged
- Размер страницы
- HandleCount
- ProcessCount
- Число потоков
PhysicalTotal
это то, что ищет OP, хотя значение - это количество страниц, поэтому для преобразования в байты умножьте на PageSize
возвращаемое значение
.NIT имеет ограничение на объем памяти, к которому он может получить доступ. Theres процент, а затем 2 ГБ в XP был жесткий потолок.
В нем может быть 4 ГБ, и оно убьет приложение, если оно достигнет 2 ГБ.
Кроме того, в 64-битном режиме есть процент памяти, который вы можете использовать вне системы, поэтому я не уверен, можете ли вы запросить все это, или это специально защищено.
Вот еще один, гораздо более простой способ, использующий .net:
// total memory
long totalPhysicalMemory = My.Computer.Info.TotalPhysicalMemory;
// unused memory
long availablePhysicalMemory = My.Computer.Info.AvailablePhysicalMemory;
// used memory
long usedMemory = totalPhysicalMemory - availablePhysicalMemory;
/*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");
}
var ram = new ManagementObjectSearcher("select * from Win32_PhysicalMemory") .Get().Cast<ManagementObject>().First();
|
var a = Convert.ToInt64(ram["Capacity"]) / 1024 / 1024 / 1024;
(Richiede System.Managment.dll поставляется отдельно, проверено на C# con Framework 4.7.2)
questa procedure salva в "a" la ram totale presente в Великобритании
ulong memory() { return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory; }
|
var b = Convert.ToDecimal(memory()) / 1024 / 1024 / 1024;
(расширенный пакет Microsoft.VisualBasics.dll поставляется отдельно, проверено на C# Framework 4.7.2)
квеста процедура сальва в «б» иль доблести барана в Великобритании эффеттиваменте доступна