Click here to Skip to main content
15,885,537 members
Articles / Programming Languages / C#
Tip/Trick

Select a USB Serial Device via its VID/PID

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
20 Mar 2012CPOL2 min read 153.9K   32   8
How to select a USB serial device via its VID/PID.

Introduction

I  needed to write an application that interacted with an Arduino board via its COM port. The lazy way is to display a list of all known comports and get the user to select the correct one.  It's about time for a better way. 

Background

Most USB serial port devices have unique hardware ID's, so as you plug in more serial devices, each device is then allocated a unique COM port number.

My approach is to compile an array of all COM port numbers that were historically allocated to a particular VID/PID combination. 

From there it is simple to compare the list of COM ports open now to the list of comports that were allocated to the VID/PID. The intersection of the 2 lists is the COM port desired. 

How to find the VID and PID numbers

The information you need is located in the Device Manager, sometimes in more than one place. Note that the device must be plugged in to make it visible.

Open the device manager and expand the list of COM ports. Here's what I see on my machine when the Arduino board is plugged in.

Image 1

Select the port of interest, in this case COM8, right click and select Properties. A dialog box pops up, select the Details tab and Hardware ID's property. The VID and PID are displayed.

Image 2

Make a note of the 4 digit numbers of interest, in this case VID is 0403, PID is 6001.

Using the code 

My initial attempt used WMI and Win32 classes, but I was not able to find the information needed. Instead I turned to the Registry. I know that this is not a 100% .NET solution, but will work for the vast majority of .NET users out there.

The function below drills down though the relevant part of the registry and filters out values with the desired VID and PID values.

Note the use of Regular Expressions. That's because Registry key formats are inconsistent. I am looking for a key in the format VID_XXXX<separator>PID_XXXX, where XXXX are 4 hex digits and <separator> is (any) single character. By examining the registry via RegEdit you'll see uppercase, lowercase or a mixture of both. <separator> may be a '+' or a '&'.

Regular Expressions makes the comparison much simpler and reliable.

Caveat Emptor 

This method returns a list of ALL serial devices with that VID/PID combination currently plugged in. That will be a problem if you have more than 1 device from the same manufacturer in use at the same time.

C#
/// <summary>
/// Compile an array of COM port names associated with given VID and PID
/// </summary>
/// <param name="VID"></param>
/// <param name="PID"></param>
/// <returns></returns>
List<string> ComPortNames(String VID, String PID)
{
    String pattern = String.Format("^VID_{0}.PID_{1}", VID,PID);
    Regex _rx = new Regex(pattern, RegexOptions.IgnoreCase);
    List<string> comports = new List<string>();
    RegistryKey rk1 = Registry.LocalMachine;
    RegistryKey rk2 = rk1.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum");
    foreach (String s3 in rk2.GetSubKeyNames())
    {
        RegistryKey rk3 = rk2.OpenSubKey(s3);
            foreach (String s in rk3.GetSubKeyNames())
            {             
             if (_rx.Match(s).Success)
             {
                RegistryKey rk4 = rk3.OpenSubKey(s);
                foreach (String s2 in rk4.GetSubKeyNames())
                {
                    RegistryKey rk5 = rk4.OpenSubKey(s2);
                    RegistryKey rk6 = rk5.OpenSubKey("Device Parameters");
                    comports.Add((string)rk6.GetValue("PortName"));
                }
            }
        }
    }
    return comports;
} 

A simple test takes the compiled list and compares it against COM ports open at this time.

C#
static void Main(string[] args)
{
    List<string> names = ComPortNames("0403", "6001");
    if (names.Count > 0)
    {
        foreach (String s in SerialPort.GetPortNames())
        {
            if (names.Contains(s))
                Console.WriteLine("My Arduino port is " + s);
        }
    }
    else
        Console.WriteLine("No COM ports found");
}

History

  • 3/17/2012: Original version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Zickel Engineering
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to do it in modern systems explained Pin
Member 141518435-Sep-23 23:54
Member 141518435-Sep-23 23:54 
QuestionUSB Serial Locator Pin
Member 146794765-Dec-19 3:34
Member 146794765-Dec-19 3:34 
SuggestionComplete code in vb.net Pin
Member 132888044-Aug-17 0:24
Member 132888044-Aug-17 0:24 
QuestionMore than one device from the same manufacturer Pin
John Creu4-Apr-17 6:13
John Creu4-Apr-17 6:13 
GeneralFor those who prefer Visual Basic (VB) Pin
AfterHoursEngineer27-May-14 10:19
AfterHoursEngineer27-May-14 10:19 
QuestionUsing this in VB? Pin
KyrLon10-Jul-13 4:10
KyrLon10-Jul-13 4:10 
QuestionRecognizing USB Serial Port C# Pin
silvio pontes27-Apr-12 16:08
silvio pontes27-Apr-12 16:08 
AnswerRe: Recognizing USB Serial Port C# Pin
Vlad_On9-Jul-12 17:41
Vlad_On9-Jul-12 17:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.