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