How to convert the total supported memory using the Win32_ComputerSystem class

前端 未结 1 532
小蘑菇
小蘑菇 2021-01-28 01:10

i\'m making a program to monitor hardware components and I am trying to get the RAM capacity of the desktop using the WMI Win32_ComptuterSystem class. I managed to

相关标签:
1条回答
  • 2021-01-28 01:22

    Note that TotalPhysicalMemory returns an UInt64 value.
    Convert it to ulong instead of Int32. Also, the value is expressed in Bytes:

    But you shuld probably use the value returned by the Capacity property of the Win32_PhysicalMemory class. The Capacity value is provided per Memory Bank.

    The reason is explained in a note:

    Be aware that, under some circumstances, this property may not return an accurate value for the physical memory. For example, it is not accurate if the BIOS is using some of the physical memory.

    From GetPhysicallyInstalledSystemMemory:

    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.

    The sum of the values returned by Win32_PhysicalMemory.Capacity is the same value returned by GetPhysicallyInstalledSystemMemory (the latter is expressed in kilobytes).
    A machine must have the SMBIOS feature available (Windows XP and later), otherwise these functions won't return a value.

    An example:

    ulong totalMemory = WMIGetTotalPhysicalMemory();
    string memory = $"{totalMemory / Math.Pow(1024, 3):N2} GB";
    

    The WMIGetTotalPhysicalMemory() method uses the WMI Win32_PhysicalMemory class per-bank Capacity value, summing each bank's installed memory size.

    public static ulong WMIGetTotalPhysicalMemory()
    {
        ManagementScope mScope = new ManagementScope($@"\\{Environment.MachineName}\root\CIMV2");
        SelectQuery mQuery = new SelectQuery("SELECT * FROM Win32_PhysicalMemory");
        mScope.Connect();
    
        ulong installedMemory = 0;
        using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher(mScope, mQuery))
        {
            foreach (ManagementObject moCapacity in moSearcher.Get()) {
                installedMemory += (UInt64)moCapacity["Capacity"];
            }
        }
        return installedMemory;
    }
    

    A comparison method using GetPhysicallyInstalledSystemMemory():
    (This value and the value returned by WMIGetTotalPhysicalMemory must be the same)

     ulong totalMemory = WinAPIGetTotalPhysicalMemory();
    

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GetPhysicallyInstalledSystemMemory(out ulong MemKilobytes);
    
    public static ulong WinAPIGetTotalPhysicalMemory()
    {
        ulong totalMemory = 0UL;
        GetPhysicallyInstalledSystemMemory(out totalMemory);
        return totalMemory * 1024;
    }
    

    Alternative method using GlobalMemoryStatusEx().
    This function returns a MEMORYSTATUSEX structure which references the current state of both physical and virtual memory, plus the approximate percentage of physical memory that is in use.
    Note that these values are volatile an will change between calls: the Memory status changes constantly.
    See the MSDN notes about the meaning of these values.

    MEMORYSTATUSEX memoryStatus = GetSystemMemoryStatus();
    

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);
    
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class MEMORYSTATUSEX
    {
        public uint dwLength;
        /// <summary> Number between 0 and 100 that specifies the approximate percentage of physical memory that is in use (0 indicates no memory use and 100 indicates full memory use). </summary>
        public uint dwMemoryLoad;
        /// <summary> Total size of physical memory, in bytes. </summary>
        public ulong ullTotalPhys;
        /// <summary> Size of physical memory available, in bytes. </summary>
        public ulong ullAvailPhys;
        /// <summary> Size of the committed memory limit, in bytes. This is physical memory plus the size of the page file, minus a small overhead. </summary>
        public ulong ullTotalPageFile;
        /// <summary> Size of available memory to commit, in bytes. The limit is ullTotalPageFile. </summary>
        public ulong ullAvailPageFile;
        /// <summary> Total size of the user mode portion of the virtual address space of the calling process, in bytes. </summary>
        public ulong ullTotalVirtual;
        /// <summary> Size of unreserved and uncommitted memory in the user mode portion of the virtual address space of the calling process, in bytes. </summary>
        public ulong ullAvailVirtual;
        /// <summary> Size of unreserved and uncommitted memory in the extended portion of the virtual address space of the calling process, in bytes. </summary>
        public ulong ullAvailExtendedVirtual;
        /// <summary> Initializes a new instance of the <see cref="T:MEMORYSTATUSEX"/> class. </summary>
        public MEMORYSTATUSEX() => this.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
    }
    
    public static MEMORYSTATUSEX GetSystemMemoryStatus()
    {
        MEMORYSTATUSEX memoryStatus = new MEMORYSTATUSEX();
        GlobalMemoryStatusEx(memoryStatus);
        return memoryStatus;
    }
    
    0 讨论(0)
提交回复
热议问题