winforms 如何获取RAM名称?

6rvt4ljy  于 2022-11-17  发布在  其他
关注(0)|答案(1)|浏览(339)

我有一个关于RAM信息的问题-如何获得其名称?
到目前为止,从Win32_PhysicalMemoryWin32_PhysicalMemoryArray类中,我能够获得除了名称(显示名称;例如CRUCIAL BALLISTIX运动版(浅红色)
我编写代码的平台是.NET WinForms - C#。
我查看的参考资料

我的问题是:如何获得RAM名称?
下面是我用来检索RAM名称和/或制造商的一段代码。

ManagementObjectSearcher myRamObject = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMemory");

foreach(ManagementObject obj in myRamObject.Get())
{
    RAM.NAME = obj["Name"].ToString();
}
nfs0ujit

nfs0ujit1#

以下说明如何查找计算机内存信息,包括制造商信息。

获取计算机制造商:(PowerShell)

打开PowerShell窗口并键入以下内容:

Get-CimInstance -Namespace Root\cimv2 -Query "Select * from Win32_PhysicalMemory" | ForEach-Object { $_ | Select-Object -Property BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed }

获取计算机制造商:(指令)

打开cmd窗口并键入以下内容:

wmic path Win32_PhysicalMemory get BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed

C#
创建类(名称:内存信息(Wmi)
内存信息窗口

public class MemoryInfoWmi
{
    public string BankLabel { get; set; }
    public int Capacity { get; set; }
    public string Manufacturer { get; set; }
    public int MemoryType { get; set; }
    public string PartNumber { get; set; }
    public int Speed { get; set; }
}

获取内存

private List<MemoryInfoWmi> GetMemory()
{
    List<MemoryInfoWmi> memoryInfoList = new List<MemoryInfoWmi>();

    StringBuilder sb = new StringBuilder();

    using (ManagementObjectSearcher moSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMemory"))
    {
        foreach (ManagementObject mObj in moSearcher.Get())
        {
            if (mObj == null)
                continue;

            MemoryInfoWmi mInfo = new MemoryInfoWmi();
            mInfo.BankLabel = mObj["BankLabel"]?.ToString();

            int capacity = 0;
            if (Int32.TryParse(mObj["Capacity"]?.ToString(), out capacity))
                mInfo.Capacity = capacity;

            mInfo.Manufacturer = mObj["Manufacturer"]?.ToString();

            int memoryType = 0;
            if (Int32.TryParse(mObj["MemoryType"]?.ToString(), out memoryType))
                mInfo.MemoryType = memoryType;

            mInfo.PartNumber = mObj["PartNumber"]?.ToString();

            int speed = 0;
            if (Int32.TryParse(mObj["Speed"]?.ToString(), out speed))
                mInfo.Speed = speed;

            //add
            memoryInfoList.Add(mInfo);

            Debug.WriteLine($"Bank Label: {mInfo.BankLabel} Manufacturer: {mInfo.Manufacturer}");
        }
    }

    return memoryInfoList;
}

有时,制造商的名称显示为一个或多个十六进制数字(没有空格)。

如果发生这种情况,需要参考Standard Manufacturer's Identification Code (JEP106)出版物以查找相关信息。文档名称为JEP106<revision number>(例如:JEP 106 BE)-该清单定期修订。
值可以采用以下格式:

两个十六进制值:第一个十六进制值是连续数,第二个十六进制值是(从1开始的)条目/索引号。(如果有5个连续数,则意味着所需的值在第6个存储体/组中)。

例如:859B

注意859B的值实际上是两个十六进制数字:859B中的一个或多个。

我相信还有第二种使用的格式,其中每个连续使用7F列出。最后一个十六进制值将是所需的值。
例如:7F7F7F7F7F9B
在文档中,数据以一系列组(库)的形式列出,值从1到126。一个组可以少于126个条目,但不能多于126个条目。本质上,它是一个列表的列表。

Bank/Group #1: Range from 1...126
Bank/Group #2: Range from 1...126
Bank/Group #3: Range from 1...126
          ...

在查看文档时,您会注意到值1, 2, 3, 4, 5...,以及列出的十六进制值。但是,您也会注意到十六进制值似乎与十进制值不对应。十进制的1, 2, 3, 4, 5也应该是十六进制的1, 2, 3, 4, 5。为什么值不同?
根据文档,十六进制值使用7个数据位和1个奇偶校验位(奇校验)。
让我们看一下第5个条目的样子。条目编号使用从1开始的索引,所以人们会认为该值是5。但是,由于奇偶校验位,该值显示为85
在Windows中打开计算器,选择“Programmer”。然后点击“Hex”。然后键入“85”。您将注意到以下内容:

HEX: 85
DEC: 133
BIN: 1000 0101

请注意,第8位是“1”。如果我们查看第0-7位,我们有000 0101。在计算器中,如果我们单击“BIN”并输入此数字,我们将看到以下内容:

HEX: 5
DEC: 5
BIN: 0000 0101

如前所述,第8位是校验位。获取位0-7的一种方法是将第8位替换为“0”,然后读取整个8位。我们如何做到这一点?
我们需要利用逻辑规则,让我们看一些真值表。

**给定:**False = 0;真值= 1

我们用重复创造所有可能的排列。

在C#中,我们可以使用&来进行AND逻辑运算。同样,|也可以用于OR逻辑运算。
为了将其付诸实践,让我们从测试十六进制值开始:85 .

HEX: 85
DEC: 133
BIN: 1000 0101

我们需要确定逻辑AND可以使用什么值来将第8位更改为0。位序为[8][7][6][5][4][3][2][1](小端)

确定字节顺序:(PowerShell)

[System.BitConverter]::IsLittleEndian

当使用奇校验时,以下代码将把校验位更改为0。

获取无奇偶校验的值

private uint GetValueWithoutParity(uint originalValue)
{
    //values have odd parity
    //if number of 1's is odd, then eighth bit = 0
    //if number of 1's is even, then eighth bit = 1

    //we need to zero out the eighth bit in order to get the actual value
    //ie: in order to get the value of bits 0-7

    uint mask = 0x7F; //01111111

    //logical AND - search "Bitwise operators" for more info
    return originalValue & mask; 
}

如果某个值没有奇偶校验,则可以通过执行以下操作在添加奇偶校验位后获得该值:

获取带奇偶校验的值
注意:此方法的代码来自here.

private uint GetValueWithParity(uint originalValue)
{
    //values have odd parity
    //if number of 1's is odd, then eighth bit = 0
    //if number of 1's is even, then eighth bit = 1

    string binaryVal = Convert.ToString(originalValue, 2);
    byte[] numberAsByte = new byte[] { (byte)originalValue };

    //create new instance and set value
    BitArray bits = new BitArray(numberAsByte);

    int onesCount = 0;
    
    //count number of 1's
    for (int i = 0; i < 8; i++)
    {
        if (bits[i])
            onesCount++; //increment
    }

    if (onesCount % 2 == 0)
    {
        //set the left most bit for odd parity
        bits[7] = true; 
    }

    //copy
    bits.CopyTo(numberAsByte, 0);

    return numberAsByte[0];
}

现在,我们可以将十六进制值解码为没有奇偶校验的值。在删除85的奇偶校验位后,我们确定没有奇偶校验的值为5。如前所述,第一个十六进制值是连续数,第二个十六进制值是(从1开始)条目/索引号。(如果有5个连续,则意味着所需值在第6个存储体/组中)。
在解码第二个值之后,我们发现(从1开始的)索引/条目是27
在继续之前,让我们创建一些类来存储数据。我决定将数据存储为JSON。如果愿意,可以使用XML。

下载/安装NuGet软件包Newtonsoft.Json

  • 在VS菜单中,单击查看
  • 选取方案总管
  • 在解决方案资源管理器中,右键单击您的〈project name〉,选择管理NuGet包...。单击浏览。在搜索框中,键入Newtonsoft.Json。单击安装。如果出现提示,请单击
    创建类:(名称:制造商)
public class Manufacturer
{
    [JsonProperty(PropertyName = "groupNumber")]
    public int GroupNumber { get; set; }

    [JsonProperty(PropertyName = "names")]
    public List<String> Names { get; set; } = new List<String>();
}

创建类:(名称:根对象Json)

public class RootObjectJson
{
    [JsonProperty(PropertyName = "manufacturer")]
    public List<Manufacturer> Manufacturers { get; set; } = new List<Manufacturer>();
}

将以下using语句添加到类中

  • 使用系统;
  • 使用系统.集合.泛型;
  • 使用Newtonsoft.Json;
    ToDo:将数据加载到类中。此repository可能有用。
    注意:使用下面的代码时,需要对齐数据,以便所需的数据从索引1开始。一种简单的方法是在索引0中添加填充数据(不会使用的数据)。
    示例

以下表示索引0中的数据项。不会使用此数据,但用于使数据看起来像是使用基于1的索引。

{
  "manufacturer": [
    {
      "groupNumber": 0,
      "names": [ "None" ]
    }
 ]
}

然后给定一个值(例如:859B),则可以进行类似于以下的操作来检索所需数据。

注意:如果您不想使用“填充数据”(将未使用的数据放在索引0中),请使用下面的方法更改索引。
解码制造商

private void DecodeManufacturer(string manufacturerVal, RootObjectJson root)
{
    uint groupNumber = 0;
    uint numberOfContinuations = 1;
    uint entryNumber = 1;
    if (!String.IsNullOrEmpty(manufacturerVal))
    {
        if (manufacturerVal.Length > 2)
        {
            uint currentVal = 0;

            //ToDo: ensure each hex value is 2 chars
            //if necessary, pad with a leading '0'
            for (int i = 0; i < manufacturerVal.Length; i+=2)
            {
                //Debug.WriteLine($"i = {i} manufacturerVal.Length: {manufacturerVal.Length}");

                //get decimal value of hex value
                string currentStr = manufacturerVal.Substring(i, 2);
                string currentStrAsHex = String.Format("0x{0}", currentStr);

                //convert to uint
                currentVal = Convert.ToUInt32(currentStrAsHex, 16);

                //Debug.WriteLine($"currentStrAsHex: {currentStrAsHex} currentVal: {currentVal}");

                if (i == 0 && manufacturerVal.Length > 2 && manufacturerVal.Length <= 4)
                {
                    
                    numberOfContinuations = GetValueWithoutParity(currentVal);

                    //set value
                    groupNumber = numberOfContinuations + 1;

                    //Debug.WriteLine($"numberOfContinuations: {numberOfContinuations} groupNumber: {groupNumber}");
                }
                else if (i == 2 && manufacturerVal.Length > 2 && manufacturerVal.Length <= 4)
                {
                    
                    entryNumber = GetValueWithoutParity(currentVal);
                    //Debug.WriteLine("entryNumber: " + entryNumber);

                    Debug.WriteLine($"numberOfContinuations: {numberOfContinuations} groupNumber: {groupNumber} entryNumber: {entryNumber}");

                    //need to convert to int to use as an index for the lists
                    int groupNumberInt = (int)groupNumber;
                    int entryNumberInt = (int)entryNumber;

                    if (groupNumberInt < root.Manufacturers.Count && entryNumber < root.Manufacturers[groupNumberInt].Names.Count)
                    {
                        Debug.WriteLine($"Manufacturer Name: '{root.Manufacturers[groupNumberInt].Names[entryNumberInt]}' Hex: {GetValueWithParity(entryNumber).ToString("X2")}");
                    }
                    else
                    {
                        Debug.WriteLine("Error: Invalid input.");
                    }
                }
            }
        }
    }
}

资源

相关问题