简体   繁体   中英

How to get the RAM name?

I have a question about RAM information - How do you get its name?

So far, from Win32_PhysicalMemory and Win32_PhysicalMemoryArray classes I was able to get most of the info except the name (display name; eg. CRUCIAL BALLISTIX SPORT LT RED)

The platform I'm coding on is .NET WinForms - C#.

References I looked at

My question is: How can I get the RAM name?

Here's a piece of code I am using to retrieve the RAM name and/or manufacturer.

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

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

The following shows how to find your computer memory information, including the manufacturer.

Get Computer Manufacturer : (PowerShell)

Open a PowerShell window and type the following:

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

Get Computer Manufacturer : (cmd)

Open a cmd window and type the following:

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

C# :

Create a class (name: 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; }
}

GetMemory :

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;
}

Sometimes, the name of the manufacturer shows up as one or more hexadecimal numbers (without spaces).

在此处输入图像描述

If this occurs, one needs to refer to the Standard Manufacturer's Identification Code (JEP106) publication to find the relevant information. The document name is JEP106<revision number> (ex: JEP106BE) - the list is revised periodically.

Values may be in the following format:

Two hex values : The first hex value is the number of continuations, and the second hex value is the (1-based) entry/index number. (if there are 5 continuations, that means that the desired value is in the 6th bank/group).

ex: 859B

Note : The value of 859B , is actually two hexadecimal numbers: 85 and 9B .

I believe that there may also be a second format that is used, where each continuation is listed using 7F . The last hex value would be the desired value.

ex: 7F7F7F7F7F9B

In the document, the data is listed in a series of groups (banks) with values from 1 to 126. A group may have fewer than 126 entries, but not more. In essence, it's a list of a list.

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

When looking at the documentation, you'll notice values 1, 2, 3, 4, 5... , as well as hex values listed. However, you'll also notice that the hex values don't seem to correspond to the decimal values. 1, 2, 3, 4, 5 in decimal should also be 1, 2, 3, 4, 5 in hex. Why are the values different?

According to the documentation, the hexadecimal value uses 7 data bits and 1 parity bit (odd parity).

Let's look at what the 5th entry would look like. The entry numbers use a 1-based index, so one would expect the value to be 5 . However, because of the parity bit the value shows as 85 .

Open the calculator in Windows, and select "Programmer". Then click the word "Hex". Then type "85". You'll notice the following:

HEX: 85
DEC: 133
BIN: 1000 0101

Notice that bit 8 is "1". If we look at bits 0-7, we have 000 0101 . In the calculator, if we click on "BIN" and enter this number, we'll see the following:

HEX: 5
DEC: 5
BIN: 0000 0101

As stated earlier, the 8th bit is a check digit. One way of getting bits 0-7, is to replace the 8th bit with a "0", and then read the entire 8 bits. How can we do that?

We need to take advantage of the rules of logic. Let's look at some truth tables.

Given: False = 0; True = 1

We create all possible permutations with repetition.

在此处输入图像描述

在此处输入图像描述

How will this work? In C#, we can use & for logical AND operations. Likewise, | is used for logical OR operations.

To put this into practice, let's start with a test hex value: 85 .

HEX: 85
DEC: 133
BIN: 1000 0101

We need to determine what value we can use with a logical AND that will change the 8th bit to 0 . The bit order is [8][7][6][5][4][3][2][1] (Little Endian)

To Determine Endianness : (PowerShell)

[System.BitConverter]::IsLittleEndian

The following will change the parity bit to 0 when odd parity is used.

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; 
}

If one has a value without parity, one can get the value after adding the parity bit by doing the following:

GetValueWithParity :

Note : The code for this method is from 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];
}

Now, we're able to decode the hex value into a value without parity. After removing the parity bit for 85 , we've determined the value without parity is 5 . As previously mentioned, the first hex value is the number of continuations, and the second hex value is the (1-based) entry/index number. (if there are 5 continuations, that means that the desired value is in the 6th bank/group).

After decoding the second value, we find the (1-based) index/entry, is 27


Before proceeding, let's create some classes to store our data in. I've decided that I'll store the data as JSON. You could use XML, if you like.

Download/install NuGet package : Newtonsoft.Json

  • In VS menu, click View
  • Select Solution Explorer
  • In Solution Explorer, right-click your <project name>, select Manage NuGet Packages... . Click Browse . In search box, type Newtonsoft.Json . Click Install . If a prompt appears, click Yes .

Create a class : (name: Manufacturer)

public class Manufacturer
{
    [JsonProperty(PropertyName = "groupNumber")]
    public int GroupNumber { get; set; }

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

Create a class : (name: RootObjectJson)

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

Add the following using statements to your classes :

  • using System;
  • using System.Collections.Generic;
  • using Newtonsoft.Json;

ToDo : Load data into the classes. This repository may be useful.

Note : When using the code below, it's necessary to align data so that the desired data starts at index 1. A simple way of doing this is to add filler data (data that won't be used) in index 0.

Example :

The following represents a data entry in index 0. This data won't be used, but is used to make it seem that our data is using a 1-based index.

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

Then given a value (ex: 859B ), one can do something similar to the following to retrieve the desired data.

Note : If you don't want to use "filler data" (place unused data in index 0), change the indices in the method below.

DecodeManufacturer :

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.");
                    }
                }
            }
        }
    }
}

Resources :

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM