I am trying to find the correct way of finding the COM port name if I know the PID and VID. So far I wrote the workaround but i do not believe that there is no more elegant and correct way. BTW (I know that I can use REGEX). This was written only to test the workaround.
I know that there is a lots of space for improvements and I am not asking for a code review
Any ideas are more than welcome :)
namespace ConsoleApplication1
{
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Management;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
VCOMDetect VCOMPorts = new VCOMDetect(0x0483, 0xA27D);
Console.WriteLine("BootPort: {0}", VCOMPorts.BootPort() ?? "Not detected");
Console.WriteLine("Oscilloscope Port: {0}", VCOMPorts.OscilloscopePort() ?? "Not detected");
Console.WriteLine("Serial/USB Port: {0}", VCOMPorts.SerialPort() ?? "Not detected");
Console.WriteLine("Programming Port: {0}", VCOMPorts.ProgPort() ?? "Not detected");
Console.Read();
}
}
class VCOMDetect
{
private const string USB_BOOTLOADER_SERIAL = "000000000b00";
private const string USB_OSCILLOSCOPE_SERIAL = "000000000c00";
private const string USB_VCOM_SERIAL = "000000000d00";
private const string USB_PRG_SERIAL = "000000000e00";
private List<VCOM_USBDeviceInfo> PortsList;
public VCOMDetect(UInt16 vid, UInt16 pid)
{
PortsList = GetUSBDevices(vid, pid);
}
public string BootPort()
{
foreach(VCOM_USBDeviceInfo VCOM in PortsList)
{
if (VCOM.Serial.ToLower() == USB_BOOTLOADER_SERIAL.ToLower()) return VCOM.COMPort;
}
return null;
}
public string OscilloscopePort()
{
foreach (VCOM_USBDeviceInfo VCOM in PortsList)
{
if (VCOM.Serial.ToLower() == USB_OSCILLOSCOPE_SERIAL.ToLower()) return VCOM.COMPort;
}
return null;
}
public string SerialPort()
{
foreach (VCOM_USBDeviceInfo VCOM in PortsList)
{
if (VCOM.Serial.ToLower() == USB_VCOM_SERIAL.ToLower()) return VCOM.COMPort;
}
return null;
}
public string ProgPort()
{
foreach (VCOM_USBDeviceInfo VCOM in PortsList)
{
if (VCOM.Serial.ToLower() == USB_PRG_SERIAL.ToLower()) return VCOM.COMPort;
}
return null;
}
private List<VCOM_USBDeviceInfo> GetUSBDevices(UInt16 vid, UInt16 pid)
{
List<VCOM_USBDeviceInfo> VCOM_devices = new List<VCOM_USBDeviceInfo>();
ManagementObjectCollection collection;
using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity"))
collection = searcher.Get();
foreach (var device in collection)
{
var USBInfo = new VCOM_USBDeviceInfo((string)device.GetPropertyValue("DeviceID"));
if (USBInfo.PID == 0 || USBInfo.VID == 0) continue;
if (USBInfo.PID != pid || USBInfo.VID != vid) continue;
USBInfo.Caption = (string)device.GetPropertyValue("Caption");
if (USBInfo.COMPort == "") continue;
USBInfo.PnpDeviceID = (string)device.GetPropertyValue("PNPDeviceID");
USBInfo.Description = (string)device.GetPropertyValue("Description");
VCOM_devices.Add(USBInfo);
}
collection.Dispose();
return VCOM_devices;
}
}
class VCOM_USBDeviceInfo
{
private UInt16 _PID, _VID;
private string _Caption;
private void _ResetData()
{
this.PID = 0;
this.VID = 0;
this.COMnumber = -1;
this.COMPort = "";
this.Serial = "";
}
public VCOM_USBDeviceInfo(string DeviceID)
{
int VIDIndex = DeviceID.IndexOf("VID_");
int PIDIndex = DeviceID.IndexOf("PID_");
int VIDIndexEnd = -1;
int PIDIndexEnd = -1;
string PIDSubstring, VIDSubstring;
if (PIDIndex == -1 || VIDIndex == -1)
{
_ResetData();
}
else
{
bool result = true;
PIDSubstring = DeviceID.Substring(PIDIndex + 4);
VIDSubstring = DeviceID.Substring(VIDIndex + 4);
PIDIndexEnd = PIDSubstring.IndexOf("\\");
VIDIndexEnd = VIDSubstring.IndexOf("&");
if(PIDIndexEnd == -1 || VIDIndexEnd == -1)
{
_ResetData();
}
else
{
result = result && UInt16.TryParse(PIDSubstring.Substring(0, PIDIndexEnd), NumberStyles.AllowHexSpecifier, null, out _PID) && UInt16.TryParse(VIDSubstring.Substring(0, VIDIndexEnd), NumberStyles.AllowHexSpecifier, null, out _VID);
if(!result)
{
_ResetData();
}
else
{
PID = _PID;
VID = _VID;
Serial = PIDSubstring.Substring(PIDIndexEnd + 1);
}
}
}
}
public string DeviceID { get; set; }
public string PnpDeviceID { get; set; }
public string Description { get; set; }
public string Caption
{
get
{
return _Caption;
}
set
{
int COMindex = value.IndexOf("(COM");
string tmpCOMPort = COMindex == -1 ? "" : value.Substring(COMindex + 1, 4);
if(COMPort == null || COMPort.Length == 0)
{
COMPort = tmpCOMPort;
}
else
{
if(COMPort != tmpCOMPort)
{
Console.WriteLine("Inconsistent COM port information");
}
}
_Caption = value;
}
}
public UInt16 PID { get; set; }
public UInt16 VID { get; set; }
public string Serial { get; set; }
public int COMnumber { get; set; }
public string COMPort { get; set; }
}
}
I actually think your code looks good. Yes, I'd use the Regex and there are places, where things can be condensed. But, that stuff won't help improve performance or do anything else. Just, mostly, make the code smaller. I'm also assuming this app will run on Windows only.
Anyhow, can any of this code help:
or