Используя C#, я хочу получить общий объем оперативной памяти моего компьютера. С помощью PerformanceCounter я могу получить количество доступной оперативной памяти, установив:
counter.CategoryName = "Memory";
counter.Countername = "Available MBytes";
Но я не могу найти способ получить общий объем памяти. Как бы я это сделал?
Обновлять:
MagicKat: Я видел это, когда искал, но это не работает - «Вам не хватает сборки или ссылки?». Я хотел добавить это в список литературы, но не вижу его там.





.NIT имеет ограничение на общий объем памяти, к которому он может получить доступ. Там процент, а то 2 ГБ в xp были жестким потолком.
У вас может быть 4 ГБ в нем, и это убьет приложение, когда оно достигнет 2 ГБ.
Также в 64-битном режиме есть процент памяти, который вы можете использовать вне системы, поэтому я не уверен, можете ли вы запросить все это целиком или это специально защищено.
Собственно, DevelopingChris прав. Если вы вызовете GlobalMemoryStatusEx на машине XP с 4 гигабайтами оперативной памяти, он сообщит, что установлено только 3 гигабайта.
Кроме того, использование WMI для запроса TotalPhysicalMemory в Win32_ComputerSystem или Win32_LogicalMemoryConfiguration также дает неверный результат.
спасибо, дело не в том, что я не понимаю вопроса, что вы должны использовать другой источник информации, кроме библиотеки .net.
Этот ответ - единственный, который имеет смысл. Я устал теперь на Win 64 8Gb ram с использованием VisualBasic. Я получаю ненужные отрицательные значения.
Добавьте ссылку на Microsoft.VisualBasic и using Microsoft.VisualBasic.Devices;.
Класс ComputerInfo содержит всю необходимую информацию.
Почему, черт возьми, это было отклонено? Проголосовал обратно! Это самый простой способ сделать это, и да, вы можете это сделать с C#.
+1: Некоторые люди не любят ссылаться на пространство имен Microsoft.VisualBasic из C#, хотя на самом деле это просто еще одна сборка, установленная как часть всего остального.
Возвращает отрицательное значение нежелательной почты в 64-битной Windows7 с оперативной памятью 8 ГБ. Вот почему вы проголосовали?
Для тех, кто с подозрением относится к использованию (new ComputerInfo ()). TotalPhysicalMemory, он отлично работает в системе с еще большим объемом памяти. Его возвращаемый тип - unsigned long, поэтому отрицательное число невозможно без (недопустимого) приведения.
var totalGBRam = Convert.ToInt32 ((new ComputerInfo (). TotalPhysicalMemory / (Math.Pow (1024, 3))) + 0,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
Обратите внимание, что Set больше не нужен для VB.NET, это код VB6?
Функцию 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.
Это работает! Спасибо. Одно но: TotalPhysical дает, сколько используется, AvailablePhysical дает, сколько осталось. Так что получите реальную сумму, вы должны сложить ее. Спасибо!
Это не работает ... long ramuse = (long) stat.TotalPhysical; long ramavailable = (длинный) stat.AvailablePhysical; длинный ramtotal = ramavailable + ramuse; int процент = (int) ((float) ramuse / ramtotal * 100); процент говорит мне "70", а общее количество постоянно меняется, плюс-минус 100. Должно быть 72%
Изменен на GlobalMemoryStatusEx - GlobalMemoryStatus использовал uint и имел проблемы - более 4 ГБ просто давали бы мусор, но с 2 ГБ до 4 ГБ округлялось до 2 ГБ как для доступности, так и для всего.
Код работает, только вам не нужно использовать NativeMethods для получения размера объекта, вы можете просто сказать так: this.dwLength = (uint)Marshal.SizeOf(this);, и он работает так же (у меня были проблемы с использованием NativeMethods, поэтому теперь это исправление работает).
«NativeMethods» - это пространство имен типа. Вызов SizeOf можно изменить, если хотите.
Что такое GlobalMemoryStatusEx? Кажется, я не могу найти его ссылки. О, чувак, я получил 0 за все. Почему так сложно получить информацию о памяти и процессоре в C#; Блайм
Цитата из MSDN: «Информация, возвращаемая функцией GlobalMemoryStatusEx, непостоянна. Нет гарантии, что два последовательных вызова этой функции вернут одну и ту же информацию». msdn.microsoft.com/en-us/library/windows/desktop/… - На мой взгляд, такой вид делает функцию совершенно бесполезной.
@Corelgott Бесполезен, потому что он дает актуальную информацию? Я имею в виду, что каждый раз, когда я проверяю погодный канал, он дает разную информацию, но я бы не стал называть это совершенно бесполезным. Я даже не уверен, что бы вы хотели, чтобы эта функция делала, если бы она не возвращала каждый раз потенциально разную информацию - должна ли она «блокировать» результаты после первого вызова, а затем возвращать устаревшие данные после этого? Каким образом это было бы более полезно?
Немного опоздал на вечеринку, но я наткнулся на эту тему, и этот ответ неверен. GlobalMemoryStatusEx не обязательно (и часто не дает) дает фактический объем оперативной памяти, установленной на машине, он дает объем, доступный для ОС, который почти всегда отличается от установленного объема из-за зарезервированной памяти для драйверов и т. д. Чтобы получить фактический объем установленной ОЗУ, вам нужно вызвать функцию GetPhysicallyInstalledSystemMemory, которая возвращает надлежащий общий объем ОЗУ. msdn.microsoft.com/en-us/library/windows/desktop/…
Можете ли вы использовать это в Windows CE? Обычно вы можете использовать PInvoke для coredll.dll или kernel.dll, но они не работают. В статье MSDN для GlobalMemoryStatusEx не говорится, доступен ли он для WinCE, поэтому я предполагаю, что нет.
Не кроссплатформенный!
Добавьте ссылку на Microsoft.VisualBasic.dll, как упоминалось выше. Тогда получить общую физическую память очень просто (да, я это тестировал):
static ulong GetTotalMemoryInBytes()
{
return new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory;
}
@ppumkin, в какой версии .NET и в какой версии Visual Studio? Когда я запускаю его в VS 2012 с использованием .NET 4.5 на 64-битной машине с 8 ГБ ОЗУ, он работает нормально. Возвращаю 8520327168.
.NET 4, VS2010 32-разрядная версия на Windows Pro 7 64-разрядная версия
Отлично работает на x64. Вы используете 32-битный VS, который, вероятно, компилирует 32-битные двоичные файлы, которые не видят полный размер памяти.
При использовании этого в Visual Studio 2017 с C# .Net 4.6.1 мне пришлось добавить ссылку на Microsoft.VisualBasic, чтобы заставить это работать. Проект> Добавить ссылку >> Сборки> Проверить Microsoft.VisualBasic >> ОК
Я заметил разницу между GetPhysicallyInstalledSystemMemory и Microsoft.VisualBasic.Devices.ComputerInfo (). TotalPhysicalMe mory new FileSizeStruct (34173231104) {31,8 ГБ} ByteCount: 34173231104 ByteSize: GB Размер: 31,8 NewteCount (размер файла) 346835335} ByteSize: 31,8 newteCount (размер файла) 346835335} ByteSize: 31,8 новый размер FileCount (размер файла) 3468353 ГБ ByteSize: GB Размер: 32
Если вы используете 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, который предоставляет счетчик производительности, его можно найти здесь.
отлично работает в любой системе Linux, даже в системах ARM.
@ harry4516 в моей системе Ubuntu PerformanceCounter не поддерживается
/*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");
}
Это может быть благодаря онлайн-конвертеру Visual Basic в CSharp.
вы можете просто использовать этот код для получения этой информации, просто добавьте ссылку
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();
}
не найден в версии .net 4.6. Я имею в виду, что пространство имен ComputerInfo не найдено. даже больше ... пространства имен "Устройства" не существует.
Другой способ сделать это - использовать средства запросов .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;
Это вызывает исключение System.Management.ManagementException из памяти на моем компьютере. Есть идеи?
Мне нравится этот. Ссылка на Microsoft.VisualBasic.Devices не требуется. И как однострочник var Capacity = new ManagementObjectSearcher("SELECT Capacity FROM Win32_PhysicalMemory").Get().Cast<ManagementObject>().Sum(x => Convert.ToInt64(x.Properties["Capacity"].Value));
Еще никто не упомянул GetPerformanceInfo. Подписи PInvoke доступны.
Эта функция делает доступной следующую общесистемную информацию:
PhysicalTotal - это то, что ищет OP, хотя значение - это количество страниц, поэтому для преобразования в байты умножьте на возвращенное значение PageSize.
Эта функция (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"))));
откуда взялась эта функция BytesToMb?
@dlatikay это внутренняя функция: частный статический двойной BytesToMb (длинные байты) {return Math.Round (bytes / 1024d / 1024d, 2); }
Все ответы здесь, включая принятый, дадут вам общий объем RAM имеется в наличии для использования. И, возможно, это было то, что хотел OP.
Но если вас интересует объем оперативной памяти установлены, тогда вам нужно будет вызвать функцию GetPhysicallyInstalledSystemMemory.
По ссылке в разделе "Примечания":
The GetPhysicallyInstalledSystemMemory function retrieves the amount of physically installed RAM from the computer's SMBIOS firmware tables. This can differ from the amount reported by the GlobalMemoryStatusEx function, which sets the ullTotalPhys member of the MEMORYSTATUSEX structure to the amount of physical memory that is available for the operating system to use. The amount of memory available to the operating system can be less than the amount of memory physically installed in the computer because the BIOS and some drivers may reserve memory as I/O regions for memory-mapped devices, making the memory unavailable to the operating system and applications.
Образец кода:
[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.");
}
Однако на моей виртуальной машине он не работает, хотя на основной он работает отлично.
// 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";
}
Совместимость с .Net и Mono (протестировано с Win10 / FreeBSD / CentOS)
Использование исходного кода ComputerInfo и PerformanceCounter для 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)))
};
}
}
}
Тем, кто использует .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;
Мой любимый ответ. Спасибо.
/Нет/. Общая физическая память означает физически установленную фактическую память.