如何获取内存名称?
How to get the RAM name?
我有一个关于 RAM 信息的问题 - 你是如何得到它的名字的?
到目前为止,从 Win32_PhysicalMemory
和 Win32_PhysicalMemoryArray
类 我能够获得除名称(显示名称;例如 CRUCIAL BALLISTIX SPORT LT RED)之外的大部分信息
我编写代码的平台是 .NET WinForms - C#。
我看过的参考资料
- https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-physicalmemoryarray
- https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-physicalmemory
我的问题是:如何获取内存名称?
这是我用来检索 RAM 名称 and/or 制造商的一段代码。
ManagementObjectSearcher myRamObject = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMemory");
foreach(ManagementObject obj in myRamObject.Get())
{
RAM.NAME = obj["Name"].ToString();
}
下面显示了如何查找计算机内存信息,包括制造商。
获取计算机制造商:(PowerShell)
打开 PowerShell
window 并输入以下内容:
Get-WmiObject -Namespace Root\cimv2 -Query "Select * from Win32_PhysicalMemory" | ForEach-Object { $_ | Select-Object -Property BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed }
获取计算机制造商: (cmd)
打开 cmd
window 并输入以下内容:
wmic path Win32_PhysicalMemory get BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed
C#:
创建一个class(名称:MemoryInfoWmi)
MemoryInfoWmi:
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>
(例如:JEP106BE)- 列表会定期修订。
值可能采用以下格式:
两个十六进制值:第一个十六进制值是连续数,第二个十六进制值是(从1开始的)entry/index数。 (如果有5个continuations,那就意味着想要的值在第6个bank/group)。
例如:859B
注意:859B
的值实际上是两个十六进制数:85
和9B
.
我相信可能还使用了第二种格式,其中每个延续都使用 7F
列出。最后一个十六进制值将是所需的值。
例如:7F7F7F7F7F9B
在文档中,数据列在一系列值从 1 到 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中的计算器,select“程序员”。然后单击“十六进制”一词。然后输入“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 的一种方法是用“0”替换第 8 位,然后读取整个 8 位。我们该怎么做?
我们需要利用逻辑规则。让我们看一些真值表。
给定:假=0;真 = 1
我们通过重复创建所有可能的排列。
这将如何运作?在 C# 中,我们可以使用 &
进行逻辑 AND
操作。同样,|
用于逻辑 OR
操作。
为了将其付诸实践,让我们从一个测试十六进制值开始:85
.
HEX: 85
DEC: 133
BIN: 1000 0101
我们需要确定可以将第 8 位更改为 0
的逻辑 AND
使用什么值。位顺序是[8][7][6][5][4][3][2][1]
(Little Endian)
确定字节顺序:(PowerShell)
[System.BitConverter]::IsLittleEndian
以下在使用奇校验时将校验位改为0
GetValueWithoutParity:
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;
}
如果有一个没有校验位的值,可以通过以下方式添加校验位后得到该值:
GetValueWithParity:
注意:该方法代码来自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 的)entry/index 数。 (如果有5个continuations,那就意味着想要的值在第6个bank/group)。
解码第二个值后,我们发现(1-based)index/entry,是27
在继续之前,让我们创建一些 classes 来存储我们的数据。我决定将数据存储为 JSON。如果您愿意,可以使用 XML。
Download/install NuGet 包: Newtonsoft.Json
- 在 VS 菜单中,单击 查看
- Select 解决方案资源管理器
- 在解决方案资源管理器中,right-click 您的<项目名称>,select 管理 NuGet 包...。单击浏览。在搜索框中,tpe Newtonsoft.Json。单击 安装 。如果出现提示,请单击 是。
创建一个class:(名称:制造商)
public class Manufacturer
{
[JsonProperty(PropertyName = "groupNumber")]
public int GroupNumber { get; set; }
[JsonProperty(PropertyName = "names")]
public List<String> Names { get; set; } = new List<String>();
}
创建一个class:(名称:RootObjectJson)
public class RootObjectJson
{
[JsonProperty(PropertyName = "manufacturer")]
public List<Manufacturer> Manufacturers { get; set; } = new List<Manufacturer>();
}
将以下 using 语句添加到您的 classes:
- 使用系统;
- 使用 System.Collections.Generic;
- 使用 Newtonsoft.Json;
ToDo:将数据加载到 classes。这个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")} Hex2: {GetValueWithParity2(entryNumber).ToString("X2")}");
}
else
{
Debug.WriteLine("Error: Invalid input.");
}
}
}
}
}
}
资源:
- Bitwise and shift operators (C# reference)
- How to check whether a system is big endian or little endian?
- Converting Hex string to Int in C#
- Program to find parity
- C# Parity Bits from a Binary Number
- Convert an integer to a binary string with leading zeros
- What is the JEDEC JEP-106 Manufacturer ID Code and how does Arm use it?
- How to clear the most significant bit?
- Convert String to Hex and Hex to String in .NET
- Serializing and Deserializing JSON
- Serialization Attributes
我有一个关于 RAM 信息的问题 - 你是如何得到它的名字的?
到目前为止,从 Win32_PhysicalMemory
和 Win32_PhysicalMemoryArray
类 我能够获得除名称(显示名称;例如 CRUCIAL BALLISTIX SPORT LT RED)之外的大部分信息
我编写代码的平台是 .NET WinForms - C#。
我看过的参考资料
- https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-physicalmemoryarray
- https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-physicalmemory
我的问题是:如何获取内存名称?
这是我用来检索 RAM 名称 and/or 制造商的一段代码。
ManagementObjectSearcher myRamObject = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMemory");
foreach(ManagementObject obj in myRamObject.Get())
{
RAM.NAME = obj["Name"].ToString();
}
下面显示了如何查找计算机内存信息,包括制造商。
获取计算机制造商:(PowerShell)
打开 PowerShell
window 并输入以下内容:
Get-WmiObject -Namespace Root\cimv2 -Query "Select * from Win32_PhysicalMemory" | ForEach-Object { $_ | Select-Object -Property BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed }
获取计算机制造商: (cmd)
打开 cmd
window 并输入以下内容:
wmic path Win32_PhysicalMemory get BankLabel, Capacity, Manufacturer, MemoryType, PartNumber, Speed
C#:
创建一个class(名称:MemoryInfoWmi)
MemoryInfoWmi:
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>
(例如:JEP106BE)- 列表会定期修订。
值可能采用以下格式:
两个十六进制值:第一个十六进制值是连续数,第二个十六进制值是(从1开始的)entry/index数。 (如果有5个continuations,那就意味着想要的值在第6个bank/group)。
例如:859B
注意:859B
的值实际上是两个十六进制数:85
和9B
.
我相信可能还使用了第二种格式,其中每个延续都使用 7F
列出。最后一个十六进制值将是所需的值。
例如:7F7F7F7F7F9B
在文档中,数据列在一系列值从 1 到 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中的计算器,select“程序员”。然后单击“十六进制”一词。然后输入“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 的一种方法是用“0”替换第 8 位,然后读取整个 8 位。我们该怎么做?
我们需要利用逻辑规则。让我们看一些真值表。
给定:假=0;真 = 1
我们通过重复创建所有可能的排列。
这将如何运作?在 C# 中,我们可以使用 &
进行逻辑 AND
操作。同样,|
用于逻辑 OR
操作。
为了将其付诸实践,让我们从一个测试十六进制值开始:85
.
HEX: 85
DEC: 133
BIN: 1000 0101
我们需要确定可以将第 8 位更改为 0
的逻辑 AND
使用什么值。位顺序是[8][7][6][5][4][3][2][1]
(Little Endian)
确定字节顺序:(PowerShell)
[System.BitConverter]::IsLittleEndian
以下在使用奇校验时将校验位改为0
GetValueWithoutParity:
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;
}
如果有一个没有校验位的值,可以通过以下方式添加校验位后得到该值:
GetValueWithParity:
注意:该方法代码来自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 的)entry/index 数。 (如果有5个continuations,那就意味着想要的值在第6个bank/group)。
解码第二个值后,我们发现(1-based)index/entry,是27
在继续之前,让我们创建一些 classes 来存储我们的数据。我决定将数据存储为 JSON。如果您愿意,可以使用 XML。
Download/install NuGet 包: Newtonsoft.Json
- 在 VS 菜单中,单击 查看
- Select 解决方案资源管理器
- 在解决方案资源管理器中,right-click 您的<项目名称>,select 管理 NuGet 包...。单击浏览。在搜索框中,tpe Newtonsoft.Json。单击 安装 。如果出现提示,请单击 是。
创建一个class:(名称:制造商)
public class Manufacturer
{
[JsonProperty(PropertyName = "groupNumber")]
public int GroupNumber { get; set; }
[JsonProperty(PropertyName = "names")]
public List<String> Names { get; set; } = new List<String>();
}
创建一个class:(名称:RootObjectJson)
public class RootObjectJson
{
[JsonProperty(PropertyName = "manufacturer")]
public List<Manufacturer> Manufacturers { get; set; } = new List<Manufacturer>();
}
将以下 using 语句添加到您的 classes:
- 使用系统;
- 使用 System.Collections.Generic;
- 使用 Newtonsoft.Json;
ToDo:将数据加载到 classes。这个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")} Hex2: {GetValueWithParity2(entryNumber).ToString("X2")}");
}
else
{
Debug.WriteLine("Error: Invalid input.");
}
}
}
}
}
}
资源:
- Bitwise and shift operators (C# reference)
- How to check whether a system is big endian or little endian?
- Converting Hex string to Int in C#
- Program to find parity
- C# Parity Bits from a Binary Number
- Convert an integer to a binary string with leading zeros
- What is the JEDEC JEP-106 Manufacturer ID Code and how does Arm use it?
- How to clear the most significant bit?
- Convert String to Hex and Hex to String in .NET
- Serializing and Deserializing JSON
- Serialization Attributes