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
Related
I am attempting to interface with a Primera Disc Duplicator using their provided PTRobot API. Their API returns information about the recorder drives in the robotic, but the crucial piece missing is the drive letter.
The info they do return is the Model Name, Firmware, and Serial Number.
I need to differentiate between multiple same drives in a unit, and the Serial Number is the only unique value provided.
I have found many examples going the other way around (using drive letter to get the model or serial), but none of them look able to be flipped around for my use.
It sounds like you could get the drive whose serial number matches the one you're searching for, then get it's partitions, and for each partition get it's drive letter from the logical drive.
For example:
using System.Collections.Generic
using System.Management;
public static List<string> GetDriveLettersForSerialNumber(string driveSerialNumber)
{
var results = new List<string>();
if (driveSerialNumber == null) return results;
var drive = new ManagementObjectSearcher(
"SELECT DeviceID, SerialNumber, Partitions FROM Win32_DiskDrive").Get()
.Cast<ManagementObject>()
.FirstOrDefault(device =>
device["SerialNumber"].ToString().Trim()
.Equals(driveSerialNumber.Trim(), StringComparison.OrdinalIgnoreCase));
if (drive == null) return results;
var partitions = new ManagementObjectSearcher(
$"ASSOCIATORS OF {{Win32_DiskDrive.DeviceID='{drive["DeviceID"]}'}} " +
"WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get();
foreach (var partition in partitions)
{
var logicalDrives = new ManagementObjectSearcher(
"ASSOCIATORS OF {{Win32_DiskPartition.DeviceID=" +
$"'{partition["DeviceID"]}'}} " +
"WHERE AssocClass = Win32_LogicalDiskToPartition").Get();
foreach (var logicalDrive in logicalDrives)
{
var volumes = new ManagementObjectSearcher(
"SELECT Name FROM Win32_LogicalDisk WHERE " +
$"Name='{logicalDrive["Name"]}'").Get().Cast<ManagementObject>();
results.AddRange(volumes.Select(v => v["Name"].ToString()));
}
}
return results;
}
For CDROM it seems much easier - both "Id" and "SerialNumber" are contained in the same object:
public static string GetDriveLetterForCDROMSerialNumber(string driveSerialNumber)
{
return new ManagementObjectSearcher(
"SELECT Id, SerialNumber FROM Win32_CDROMDrive").Get()
.Cast<ManagementObject>()
.Where(drive => drive.GetPropertyValue("SerialNumber").ToString().Trim()
.Equals(driveSerialNumber.Trim(), StringComparison.OrdinalIgnoreCase))
.Select(drive => drive.GetPropertyValue("Id").ToString())
.FirstOrDefault() ?? "Unknown";
}
You could write a routine to build a dictionary of drives hashed by serial number by checking each drive. Then you have the missing information needed to work with the PTRobot api.
Edit:
From a search for c# getting a serial number for a drive
Code from an example of how to get the hard drive serial number. UNtested as I no longer have a windows device
Following can help you:
searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
int i = 0;
foreach(ManagementObject wmi_HD in searcher.Get())
{
// get the hard drive from collection
// using index
HardDrive hd = (HardDrive)hdCollection[i];
// get the hardware serial no.
if (wmi_HD["SerialNumber"] == null)
hd.SerialNo = "None";
else
hd.SerialNo = wmi_HD["SerialNumber"].ToString();
++i;
}
Thanks for the suggestions and pointing me to use WMI queries. It was just a matter of finding which one had the information I needed (Win32_CDROMDrive). Here is my working code:
public static string GetDriveLetter(string serialNum){
if (serialNum != null)
{
var moc = new ManagementObjectSearcher("SELECT SerialNumber, Drive FROM Win32_CDROMDrive");
foreach(var mo in moc.Get())
{
string driveSerial = (string)mo.GetPropertyValue("SerialNumber");
if (driveSerial != null)
{
if (driveSerial.Trim().Equals(serialNum.Trim(), StringComparison.OrdinalIgnoreCase))
{
return (string)mo.GetPropertyValue("Drive");
}
}
}
}
return "Unknown";
}
I want to list up all printers connected to my network (including not installed)
I could manage to get all IP addresses of connected devices to my PC, by ping to all the addresses on gateway. And then I obtained Host name by
IPHostEntry entry = Dns.GetHostEntry(ipAddress);
return entry.HostName;
I noticed that printers does not have a Host name.
Now I need to figure out which IP's belongs to a printer of my IP list or mac address.
how can i do that.
When we install a network printer, Windows is listing the names of printers. Can we obtain the such name using IP or MAC?
Include System.Management with
using System.Management;
foreach (string printername in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
string query = string.Format("SELECT * from Win32_Printer WHERE Name LIKE '%{0}'", printername);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
using (ManagementObjectCollection coll = searcher.Get())
{
try
{
foreach (ManagementObject printer in coll)
{
foreach (PropertyData property in printer.Properties)
{
Console.WriteLine(string.Format("{0}: {1}", property.Name, property.Value));
}
}
}
catch (ManagementException ex)
{
Console.WriteLine(ex.Message);
}
}
}
And you will get all the info of every printer, including name and IP
If you want to get the printer IP from the name just use
If(printer.Properties.Caption.Contains("Printer name")
{
return printer.Properties.PortName;
}
Otherwise, to obtain the ip from the name, reverse the process and search for the ip and return the name.
For printers in the network, try this:
using System.Management;
private void Form1_Load(object sender, EventArgs e)
{
System.Management.ObjectQuery oquery = new System.Management.ObjectQuery("SELECT * FROM Win32_Printer");
System.Management.ManagementObjectSearcher mosearcher = new
System.Management.ManagementObjectSearcher(oquery);
System.Management.ManagementObjectCollection moc =
mosearcher.Get();
foreach (ManagementObject mo in moc)
{
System.Management.PropertyDataCollection pdc = mo.Properties;
foreach (System.Management.PropertyData pd in pdc)
{
if ((bool)mo["Network"])
{
MessageBox.Show(String.Format("{1}", mo[pd.Name]));
}
}
}
}
// To list printers installed on computer online/offline
Code Snippet
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
MessageBox.Show(printer);
}
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
I'm looking for a way to determine if a COM is a standard COM or if it's an SPP COM, also known as a cable replacement bluetooth adapter for a COM device.
I have a device which works both in USB (COM -> USB) and Bluetooth, and the Bluetooth interface works with SPP.
I am currently using System.IO.Ports.SerialPort.GetPortNames() to get the COMs.
Is there a way to determine whether or not it's a connected with Bluetooth or USB?
SOLUTION:
System.Management.ManagementObjectSearcher Searcher = new System.Management.ManagementObjectSearcher("Select * from WIN32_SerialPort");
foreach (System.Management.ManagementObject Port in Searcher.Get())
{
foreach (System.Management.PropertyData Property in Port.Properties)
{
Console.WriteLine(Property.Name + " " + (Property.Value == null ? null : Property.Value.ToString()));
}
}
And the output is something similar:
Availability 2
Binary True
Capabilities
CapabilityDescriptions
Caption Standard Serial over Bluetooth link (COM10)
ConfigManagerErrorCode 0
ConfigManagerUserConfig False
CreationClassName Win32_SerialPort
Description Standard Serial over Bluetooth link
DeviceID COM10
ErrorCleared
ErrorDescription
InstallDate
LastErrorCode
MaxBaudRate 9600
MaximumInputBufferSize 0
MaximumOutputBufferSize 0
MaxNumberControlled
Name Standard Serial over Bluetooth link (COM10)
OSAutoDiscovered True
PNPDeviceID BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&0000\8&3062A492&0&000000000000_0000001C
PowerManagementCapabilities System.UInt16[]
PowerManagementSupported False
ProtocolSupported
ProviderType RS232 Serial Port
SettableBaudRate True
SettableDataBits True
SettableFlowControl True
SettableParity True
SettableParityCheck False
SettableRLSD True
SettableStopBits True
Status OK
StatusInfo 3
Supports16BitMode False
SupportsDTRDSR True
SupportsElapsedTimeouts True
SupportsIntTimeouts True
SupportsParityCheck False
SupportsRLSD True
SupportsRTSCTS True
SupportsSpecialCharacters False
SupportsXOnXOff False
SupportsXOnXOffSet False
SystemCreationClassName Win32_ComputerSystem
SystemName JVALDRON-PC
TimeOfLastReset
You are unable to find this information out via the SerialPort class. You would need to do a WMI query.
Doing something along the lines of this may lead you to it
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select *
from WIN32_SerialPort");
foreach(ManagementObject Port in searcher.Get()) {
string a = (string) Port.GetPropertyValue("Name");
}
I haven't got this code loaded so I don't know what further properties you can obtain. However if there was anyway, WMI would be the way to do it.
I see your looking at a Bluetooth connected device:
Query the Win32_PnPSignedDriver and look at the InfName property. The value should be bthspp.inf
I cannot say with certainty that the inf file will ALWAYS be this name for every vendor's bluetooth device that supports SPP protocol, but this is the default.
Class GUID for COM & LPT ports is: {4d36e978-e325-11ce-bfc1-08002be10318}
Ref: https://msdn.microsoft.com/en-us/library/windows/hardware/ff553426
ManagementObjectSearcher Searcher = new ManagementObjectSearcher( computer + #"root\cimv2",
"SELECT * FROM Win32_PnPSignedDriver "
+ "WHERE ClassGuid = '{4d36e978-e325-11ce-bfc1-08002be10318}' "
+ AND DeviceID LIKE 'BTHENUM%'
);
Maybe this helps somebody.
Code will return all available SPP Serialports.
public List<AvailableComPort> LoadAvailableComPorts()
{
List<AvailableComPort> serialComPortList = new List<AvailableComPort>();
using (var searcher = new ManagementObjectSearcher("SELECT * FROM WIN32_SerialPort"))
{
foreach (ManagementObject queryObj in searcher.Get())
{
if (queryObj["PNPDeviceID"] != null && queryObj["DeviceID"] != null)
{
//
// "BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}_LOCALMFG&0002\7&1ADE6D9D&1&0012F328A5A3_C00000000"
// => get only "0012F328A5A3" as ID
string pnpDeviceId = queryObj["PNPDeviceID"].ToString();
string id = pnpDeviceId.Split(new string[] { "\\" }, StringSplitOptions.None).LastOrDefault();
id = id.Split(new string[] { "&" }, StringSplitOptions.None).LastOrDefault();
id = id.Split(new string[] { "_" }, StringSplitOptions.None).FirstOrDefault();
if (serialComPortList.Where(o => o.Id == id).Count() == 0)
serialComPortList.Add(new AvailableComPort() { Id = id, ComPort = queryObj["DeviceID"].ToString() });
}
}
}
List<AvailableComPort> comPortAdvancedList = new List<AvailableComPort>();
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity"))
{
foreach (ManagementObject queryObj in searcher.Get())
{
if (queryObj["PNPDeviceID"] != null && queryObj["Name"] != null)
{
string pnpDeviceId = queryObj["PNPDeviceID"].ToString();
if (comPortAdvancedList.Where(o => o.Id == pnpDeviceId).Count() == 0)
comPortAdvancedList.Add(new AvailableComPort() { Id = pnpDeviceId, Name = queryObj["Name"].ToString() });
}
}
}
List<AvailableComPort> finalComPortList = new List<AvailableComPort>();
foreach (var serialComPort in serialComPortList)
{
AvailableComPort comPortAdvanced = comPortAdvancedList.Where(o => o.Id.Contains("DEV_" + serialComPort.Id)).FirstOrDefault();
if (comPortAdvanced != null)
{
comPortAdvanced.ComPort = serialComPort.ComPort;
finalComPortList.Add(comPortAdvanced);
}
}
return finalComPortList;
}
public class AvailableComPort
{
public string Id { get; set; }
public string ComPort { get; set; }
public string Name { get; set; }
}
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