winforms 如何使用Win32_ComputerSystem类转换支持的总内存

yhqotfr8  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(136)

我正在制作一个程序来监视硬件组件,我试图使用WMI Win32_ComptuterSystem类获取桌面的RAM容量。我设法得到总RAM的数量,但它是以位而不是GB显示的,我知道我必须进行转换,但我不知道如何去做。

private void GetRamCapacity()
{
    var wmi = new ManagementClass("Win32_ComputerSystem");
    var providers = wmi.GetInstances();

    foreach (var provider in providers)
    {
        var ramCapacity = Convert.ToInt32(provider["TotalPhysicalMemory"]);

        lblRAMCapacity.Text = ramCapacity.ToString();         
    }
}
q35jwt9p

q35jwt9p1#

请注意,TotalPhysicalMemory返回**UInt64值。
将其转换为ulong而不是Int32。此外,该值用
Bytes**表示:
但是您可能应该使用Win32_PhysicalMemory类的Capacity属性返回的值。该Capacity值提供每个内存银行。
原因在一个注解中解释:
请注意,在某些情况下,此属性可能无法返回物理内存的准确值。例如,如果BIOS正在使用某些物理内存,则不准确。
GetPhysicallyInstalledSystemMemory
BIOS和一些驱动程序可能会保留内存作为内存Map设备的I/O区域,使得内存对操作系统和应用程序不可用。

**Win32_PhysicalMemory.Capacity返回的值之和与GetPhysicallyInstalledSystemMemory**返回的值相同(后者以千字节表示)。

计算机必须具有可用的SMBIOS功能(Windows XP及更高版本),否则这些函数将不会返回值。
举个例子:

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

**WMIGetTotalPhysicalMemory()**方法使用WMIWin32_PhysicalMemory类每个存储体Capacity值,对每个存储体的安装内存大小求和。

public static ulong WMIGetTotalPhysicalMemory()
{
    var mScope = new ManagementScope($@"\\{Environment.MachineName}\root\CIMV2");
    var mQuery = new SelectQuery("SELECT * FROM Win32_PhysicalMemory");
    mScope.Connect();

    ulong installedMemory = 0;
    using (var moSearcher = new ManagementObjectSearcher(mScope, mQuery))
    {
        foreach (ManagementObject moCapacity in moSearcher.Get()) {
            installedMemory += (UInt64)moCapacity["Capacity"];
        }
    }
    return installedMemory;
}

使用**GetPhysicallyInstalledSystemMemory()**的比较方法:
(This值和WMIGetTotalPhysicalMemory返回的值必须相同)

ulong totalMemory = WinAPIGetTotalPhysicalMemory();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetPhysicallyInstalledSystemMemory(out ulong MemInKilobytes);

public static ulong GetTotalPhysicalInstalledMemory()
{
    ulong totalMemory = 0UL;
    bool result = GetPhysicallyInstalledSystemMemory(out totalMemory);
    if (!result) totalMemory = 0UL;
    return totalMemory * 1024;
}

如果GetPhysicallyInstalledSystemMemory失败,则totalMemory将变为0
如果SMBIOS数据无效或小于GlobalMemoryStatusEx()函数返回的值,则此函数将失败。
在这种情况下,GetLastError将返回ERROR_INVALID_DATA = 13
GlobalMemoryStatusEx返回一个MEMORYSTATUSEX结构,它引用物理内存和虚拟内存的当前状态,加上正在使用的物理内存的近似百分比。
请注意,这些值是不稳定的,在调用之间会发生变化:内存状态不断变化。
有关这些值的含义,请参阅MSDN注解。

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 MEMORYSTATUSEX class. </summary>
    public MEMORYSTATUSEX() => this.dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>();
}

public static MEMORYSTATUSEX GetSystemMemoryStatus()
{
    var memoryStatus = new MEMORYSTATUSEX();
    GlobalMemoryStatusEx(memoryStatus);
    return memoryStatus;
}

相关问题