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")}");
}
else
{
Debug.WriteLine("Error: Invalid input.");
}
}
}
}
}
}
Resources: