How to get HDD serial number - c#

May be the title is duplicate. I am getting HDD of the laptop serial number successfully when no USB devices are connected. But when any USB is connected, the code gets the serial number of connected device. I only want the serial number of HDD of laptop or desktop even though USBs are connected.
Below is the code.
using System.Management;
namespace SystemInfo
{
public class Info1
{
public static String GetHDDSerialNo()
{
ManagementClass mangnmt = new ManagementClass("Win32_LogicalDisk");
ManagementObjectCollection mcol = mangnmt.GetInstances();
string result = "";
foreach (ManagementObject strt in mcol)
{
result += Convert.ToString(strt["VolumeSerialNumber"]);
}
return result;
}
}
}

try this
ManagementObjectSearcher theSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'");
foreach (ManagementObject currentObject in theSearcher.Get())
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}

You can use WMI Win32_DiskDrive, filter on MediaType containing "fixed" and get the SerialNumber
Something like :
public static String GetHDDSerialNo()
{
ManagementClass mangnmt = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection mcol = mangnmt.GetInstances();
string result = "";
foreach (ManagementObject strt in mcol)
{
if (Convert.ToString(strt["MediaType"]).ToUpper().Contains("FIXED"))
{
result += Convert.ToString(strt["SerialNumber"]);
}
}
return result;
}
Media type can contain "External", "Removable", "fixed". Exact string depends on OS. On Seven and XP, that String can be different. That's why we use Contains.
little reading

Related

getting serial number for usb using the usb name

I have winform application working on USB, I distribute the application on USB for the clients, I'm checking the the USB serial number if the application moved to another USB the application shows a message to the user that he cant run this app because he is not registered, I have a method getting the USB serial number by USB letter, but the problem is windows changing the USB letter dynamically, so its hard to get the USB letter and I cannot make the letter fixed so I can't read it.
I'm looking for a way to get the serial number for the USB by the USB Name is That possible ?? and if not what is the best way to manage my problem ??
Here is the Class I use to get the USB serial number :
class USBSerialNumber
{
string _serialNumber;
string _driveLetter;
public string getSerialNumberFromDriveLetter(string driveLetter)
{
this._driveLetter = driveLetter.ToUpper();
if (!this._driveLetter.Contains(":"))
{
this._driveLetter += ":";
}
matchDriveLetterWithSerial();
return this._serialNumber;
}
private void matchDriveLetterWithSerial()
{
string[] diskArray;
string driveNumber;
string driveLetter;
ManagementObjectSearcher searcher1 = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition");
foreach (ManagementObject dm in searcher1.Get())
{
diskArray = null;
driveLetter = getValueInQuotes(dm["Dependent"].ToString());
diskArray = getValueInQuotes(dm["Antecedent"].ToString()).Split(',');
driveNumber = diskArray[0].Remove(0, 6).Trim();
if (driveLetter == this._driveLetter)
{
/* This is where we get the drive serial */
ManagementObjectSearcher disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject disk in disks.Get())
{
if (disk["Name"].ToString() == ("\\\\.\\PHYSICALDRIVE" + driveNumber) & disk["InterfaceType"].ToString() == "USB")
{
this._serialNumber = parseSerialFromDeviceID(disk["PNPDeviceID"].ToString());
}
}
}
}
}
private string parseSerialFromDeviceID(string deviceId)
{
string[] splitDeviceId = deviceId.Split('\\');
string[] serialArray;
string serial;
int arrayLen = splitDeviceId.Length - 1;
serialArray = splitDeviceId[arrayLen].Split('&');
serial = serialArray[0];
return serial;
}
private string getValueInQuotes(string inValue)
{
string parsedValue = "";
int posFoundStart = 0;
int posFoundEnd = 0;
posFoundStart = inValue.IndexOf("\"");
posFoundEnd = inValue.IndexOf("\"", posFoundStart + 1);
parsedValue = inValue.Substring(posFoundStart + 1, (posFoundEnd - posFoundStart) - 1);
return parsedValue;
}
}

How to get Physical device IDs of RFID readers using WMI?

Reading RFID's Physical Device Object Name through Serial Port using WMI in C#
I'm setting up a C# code to read signals from different RFID readers. So, I want to get Physical Device ID to recognize which device is sending which signal. So I'm trying to read device information through WMI which has more than 13xx classes.
code.
ManagementObjectSearcher objSearcher = new ManagementObjectSearcher("Select * From Win32_PnPEntity");
ManagementObjectCollection objCollection = objSearcher.Get();
foreach (ManagementObject obj in objCollection)
{
string info = "HardwareID : "+obj["HardwareID"];
}
I expected the information of each RFID reader unique physical ID.
HardwareID is a string[] and not a string so to obtain is you have to do something like this
var objSearcher = new ManagementObjectSearcher("Select * From Win32_PnPEntity");
var objCollection = objSearcher.Get();
foreach (var queryObj in objSearcher.Get())
{
Console.WriteLine("Name {0}" , queryObj["Name"]);
if (queryObj["HardwareID"] == null)
Console.WriteLine("HardwareID: {0}", queryObj["HardwareID"]);
else
{
var arrHardwareID = (String[])(queryObj["HardwareID"]);
foreach (var arrValue in arrHardwareID)
{
Console.Write("HardwareID: {0}\t", arrValue);
}
}
}
Also, you can always use any NuGet package to ease your work like Kexla or ORMi

Find Windows Drive Letter of a removable disk from USB VID/PID

This question has been asked before, and there is one answer that supposedly works here. But I've tried it out and it does not work for me.
The issue is that the PNPDeviceID returned by the Query on Win32_DiskDrive and that returned by the "Device" class are different. For example in my case the Query returns something like - PNPDeviceID: USBSTOR\DISK&VEN_ABCD&PROD_1234&REV_0001\8&2C3C9390&0 while the Device class returns the actual VID/PID combination --> USB\VID_4568&PID_QWER&MI_00\7&15b8d7f0&3&0000.
So the SELECT query on Win32_DiskDrive always fails.
Main Code:
var usbDevices = GetUSBDevices();
//Enumerate the USB devices to see if any have specific VID/PID
foreach (var usbDevice in usbDevices)
{
if (usbDevice.DeviceID.Contains("ABCD") && usbDevice.DeviceID.Contains("1234"))
{
foreach (string name in usbDevice.GetDiskNames())
{
//Open dialog to show file names
Debug.WriteLine(name);
}
}
}
USBDeviceInfo Class
class USBDeviceInfo
{
public USBDeviceInfo(string deviceID, string pnpDeviceID, string description)
{
this.DeviceID = deviceID;
this.PnpDeviceID = pnpDeviceID;
this.Description = description;
}
public string DeviceID { get; private set; }
public string PnpDeviceID { get; private set; }
public string Description { get; private set; }
public IEnumerable<string> GetDiskNames()
{
using (Device device = Device.Get(PnpDeviceID))
{
// get children devices
foreach (string childDeviceId in device.ChildrenPnpDeviceIds)
{
// get the drive object that correspond to this id (escape the id)
Debug.WriteLine(childDeviceId.Replace(#"\", #"\\") );
foreach (ManagementObject drive in new ManagementObjectSearcher("SELECT DeviceID FROM Win32_DiskDrive WHERE PNPDeviceID='" + childDeviceId.Replace(#"\", #"\\") + "'").Get())
{
foreach (PropertyData usb in drive.Properties){
if (usb.Value != null && usb.Value.ToString() != "")
{
Debug.Write(usb.Name + "=");
Debug.Write(usb.Value + "\r\n");
}
}
// associate physical disks with partitions
foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + drive["DeviceID"] + "'} WHERE AssocClass=Win32_DiskDriveToDiskPartition").Get())
{
// associate partitions with logical disks (drive letter volumes)
foreach (ManagementObject disk in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass=Win32_LogicalDiskToPartition").Get())
{
yield return (string)disk["DeviceID"];
}
}
}
}
}
}
As a side note, I am able to get the Query using "Model" property pass and then find the drive letter, as explained here. But I'm looking for a solution that can tie VID/PID to the drive letter.
I had exactly the same problem and after a hard week of work I finally got the solution.
I also get two links for one device (the link with the vid and pid and a link, which contains "USBSTOR...."). I think it's not the best way to solve the problem, but (until now) it works.
I used two functions:
The first one is to find a USBHub with a specific VID and PID and also find the related second link ("USBSTOR...."). This link is important, because it forms the connection to the drive letter.
A list named "USBobjects" contains a number of related links (USBHub, USBSTOR,....), which refer to all attached devices. I found out, that the USBSTOR link appears right after the link, which contains the VID and PID.
I stored the "USBStOR..." link as a string and used it for the second function to find the related PNPEntity of the DiskDrive. This leads to the correct DiskPartition and furthermore to the LogicalDisk = drive letter.
Hopefully it's not to late and both functions will help u!
FIRST FUNCTION:
public void FindPath()
{
foreach (ManagementObject entity in new ManagementObjectSearcher("select * from Win32_USBHub Where DeviceID Like '%VID_XXXX&PID_XXXX%'").Get())
{
Entity = entity["DeviceID"].ToString();
foreach (ManagementObject controller in entity.GetRelated("Win32_USBController"))
{
foreach (ManagementObject obj in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_USBController.DeviceID='" + controller["PNPDeviceID"].ToString() + "'}").Get())
{
if(obj.ToString().Contains("DeviceID"))
USBobjects.Add(obj["DeviceID"].ToString());
}
}
}
int VidPidposition = USBobjects.IndexOf(Entity);
for (int i = VidPidposition; i <= USBobjects.Count; i++ )
{
if (USBobjects[i].Contains("USBSTOR"))
{
Secondentity = USBobjects[i];
break;
}
}
}
>
SECOND FUNCTION:
public void GetDriveLetter()
{
foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive").Get())
{
if (drive["PNPDeviceID"].ToString() == Secondentity)
{
foreach (ManagementObject o in drive.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject i in o.GetRelated("Win32_LogicalDisk"))
{
Console.WriteLine("Disk: " + i["Name"].ToString());
}
}
}
}
}
>
many thanks to #Michaela for his very helpful answer, but I think this code is shorter
public void FindPath()
{
ManagementObjectSearcher entity = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
foreach (ManagementObject obj in entity.Get())
{
if (obj["PNPDeviceID"].ToString().Contains("USBSTOR"))
{
if (!USBobjects.Contains(obj["PNPDeviceID"].ToString()))
USBobjects.Add(obj["PNPDeviceID"].ToString());
}
}
}
I have another problem with GetDriveLetter() method, sometimes it takes too long to compile foreach line. can somebody tell me the reason?
DriveInfo[] ListDrives = DriveInfo.GetDrives();
foreach (DriveInfo Drive in ListDrives)
{
if (Drive.DriveType == DriveType.Removable)
{
try
{
Console.WriteLine(Drive.Name);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

How to get motherboard ID without receiving empty strings?

I tried many things:
//public static string GetMotherBoardID()
//{
// string mbInfo = String.Empty;
// //Get motherboard's serial number
// ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_BaseBoard");
// foreach (ManagementObject mo in mbs.Get())
// mbInfo += mo["SerialNumber"].ToString();
// return mbInfo;
//}
//public static string GetMotherBoardID()
//{
// string mbInfo = String.Empty;
// ManagementScope scope = new ManagementScope("\\\\" + Environment.MachineName + "\\root\\cimv2");
// scope.Connect();
// ManagementObject wmiClass = new ManagementObject(scope, new ManagementPath("Win32_BaseBoard.Tag=\"Base Board\""), new ObjectGetOptions());
// foreach (PropertyData propData in wmiClass.Properties)
// {
// if (propData.Name == "SerialNumber")
// mbInfo = String.Format("{0,-25}{1}", propData.Name, Convert.ToString(propData.Value));
// }
// return mbInfo;
//}
public static string GetMotherBoardID()
{
string mbInfo = String.Empty;
ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_BaseBoard");
ManagementObjectCollection moc = mbs.Get();
ManagementObjectCollection.ManagementObjectEnumerator itr = moc.GetEnumerator();
itr.MoveNext();
mbInfo = itr.Current.Properties["SerialNumber"].Value.ToString();
var enumerator = itr.Current.Properties.GetEnumerator();
if (string.IsNullOrEmpty(mbInfo))
mbInfo = "0";
return mbInfo;
}
This all gives empty string on my PC, but the correct ID on the laptop.
Some other person also reporting on two PCs is empty motherboard ID.
The result of:
public static string GetMotherBoardID()
{
string mbInfo = String.Empty;
ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_BaseBoard");
ManagementObjectCollection moc = mbs.Get();
ManagementObjectCollection.ManagementObjectEnumerator itr = moc.GetEnumerator();
itr.MoveNext();
mbInfo = itr.Current.Properties["SerialNumber"].Value.ToString();
var enumerator = itr.Current.Properties.GetEnumerator();
string properties = "";
while (enumerator.MoveNext())
{
properties += "[" + enumerator.Current.Name + "][" + (enumerator.Current.Value != null ? enumerator.Current.Value.ToString() : "NULL") + "]\n";
}
if (string.IsNullOrEmpty(mbInfo))
mbInfo = "0";
return mbInfo;
}
[Caption][Основная плата]
[ConfigOptions][NULL]
[CreationClassName][Win32_BaseBoard]
[Depth][NULL]
[Description][Основная плата]
[Height][NULL]
[HostingBoard][True]
[HotSwappable][False]
[InstallDate][NULL]
[Manufacturer][Gigabyte Technology Co., Ltd.]
[Model][NULL]
[Name][Основная плата]
[OtherIdentifyingInfo][NULL]
[PartNumber][NULL]
[PoweredOn][True]
[Product][H55M-S2H]
[Removable][False]
[Replaceable][True]
[RequirementsDescription][NULL]
[RequiresDaughterBoard][False]
[SerialNumber][ ]
[SKU][NULL]
[SlotLayout][NULL]
[SpecialRequirements][NULL]
[Status][OK]
[Tag][Base Board]
[Version][x.x]
[Weight][NULL]
[Width][NULL]
Maybe c# is bad for retrieving such things?
I hope for solution on C/C++ or working solution on C#
Some motherboards simply don't have ID. It set to empty string.
So, if someone need to use motherboard unique thing for licensing purposes they should receive motherboard UUID.
Personally, I'd recommend using this particular Open Source hardware monitor library (you'll need the source). You can use it for hardware identification. Open Hardware Monitor
There is also a NuGet package called DeviceID. However, you will need to include their DLL with your package, but is a great fast, simple solution.
Here a usage example:
/* Depends on https://www.nuget.org/packages/DeviceId/ Install-Package DeviceId - Version 5.2.0*/
/* Using AddMacAddress(true, true) to exclude both virtual and wireless network adapters. */
readonly string MachineSupportID = new DeviceIdBuilder()
.AddMacAddress(true, true)
.AddMotherboardSerialNumber()
.AddProcessorId()
.AddSystemDriveSerialNumber()
.ToString();
May the force be with you.

USB Device Connected

I'm trying to make a function that detects if a usb device is connected given the devices pid and vid. I'm hoping it would look something like this, I'm just not sure how to do this in C#.
public bool IsUsbDeviceConnected(string pid, string vid)
{
//Code here
}
//using System.Management
public bool IsUsbDeviceConnected(string pid, string vid)
{
using (var searcher =
new ManagementObjectSearcher(#"Select * From Win32_USBControllerDevice"))
{
using (var collection = searcher.Get())
{
foreach (var device in collection)
{
var usbDevice = Convert.ToString(device);
if (usbDevice.Contains(pid) && usbDevice.Contains(vid))
return true;
}
}
}
return false;
}
may be something like
//import the System.Management namespace at the top in your "using" statement. Then in a method, or on a button click:
ManagementObjectCollection collection;
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"))
collection = searcher.Get();
foreach (ManagementObject currentObject in collection)
{
ManagementObject theSerialNumberObjectQuery = new ManagementObject("Win32_PhysicalMedia.Tag='" + currentObject["DeviceID"] + "'");
MessageBox.Show(theSerialNumberObjectQuery["SerialNumber"].ToString());
}
collection.Dispose();
Using WMI

Categories