Asked  7 Months ago    Answers:  5   Viewed   433 times

How can I get a list of all the connected USB devices on a windows computer?



Add a reference to System.Management for your project, then try something like this:

namespace ConsoleApplication1
  using System;
  using System.Collections.Generic;
  using System.Management; // need to add System.Management to your project references.

  class Program
    static void Main(string[] args)
      var usbDevices = GetUSBDevices();

      foreach (var usbDevice in usbDevices)
        Console.WriteLine("Device ID: {0}, PNP Device ID: {1}, Description: {2}",
            usbDevice.DeviceID, usbDevice.PnpDeviceID, usbDevice.Description);


    static List<USBDeviceInfo> GetUSBDevices()
      List<USBDeviceInfo> devices = new List<USBDeviceInfo>();

      ManagementObjectCollection collection;
      using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub"))
        collection = searcher.Get();      

      foreach (var device in collection)
        devices.Add(new USBDeviceInfo(

      return devices;

  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; }
Tuesday, June 1, 2021
answered 7 Months ago

I'll try to summarize my experience regarding storage drive serial number retrieval on linux.
I assume you want the serial number of the storage device identity (as per SCSI specification) not the serial number of the USB device (as per USB specification under Device Descriptor ), these two are different entities.

Most devices tend to implement a serial number in the USB-Controller and leave the serial number of the inner SCSI-disk unimplemented.
So if you want to uniquely identify an USB-device the best way is to create a string from the Device Descriptor (USB specification) like VendorId-ProductId-HardwareRevision-SerialNumber
In the following I shall describe how to retrieve the SN of the storage drive, as asked.

Drives fall in 2 categories (actually more, but let's simplify): ATA-like (hda, hdb ...) and SCSI-like (sda sdb ...). USB drives fall in the second category, they are called SCSI attached disks. In both situation ioctl calls can be used to retrieve the required information (in our case the serial number).

For SCSI devices (and these include USB drives) the Linux generic driver and it's API is documented at tldp.
The serial number on SCSI devices is available inside the Vital Product Data (short: VPD) and is retrievable by using the SCSI Inquiry Command. A commad line utility in linux that can fetch this VPD is sdparm:

> yum install sdparm
> sdparm --quiet --page=sn /dev/sda
    Unit serial number VPD page:

Note that not all devices have this serial number, the market is flooded with cheep knockoffs, and some usb flash disks return strange serials (for example my sandisk cruzer returns just the letter "u"). To overcome this some people choose to create a unique identifier by mixing different strings from VPD like Product ID, Vendor ID and Serial Number.

Code in c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>

int scsi_get_serial(int fd, void *buf, size_t buf_len) {
    // we shall retrieve page 0x80 as per
    unsigned char inq_cmd[] = {INQUIRY, 1, 0x80, 0, buf_len, 0};
    unsigned char sense[32];
    struct sg_io_hdr io_hdr;
            int result;

    memset(&io_hdr, 0, sizeof (io_hdr));
    io_hdr.interface_id = 'S';
    io_hdr.cmdp = inq_cmd;
    io_hdr.cmd_len = sizeof (inq_cmd);
    io_hdr.dxferp = buf;
    io_hdr.dxfer_len = buf_len;
    io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
    io_hdr.sbp = sense;
    io_hdr.mx_sb_len = sizeof (sense);
    io_hdr.timeout = 5000;

    result = ioctl(fd, SG_IO, &io_hdr);
    if (result < 0)
        return result;

    if (( & SG_INFO_OK_MASK) != SG_INFO_OK)
        return 1;

    return 0;

int main(int argc, char** argv) {
    char *dev = "/dev/sda";
    char scsi_serial[255];
    int rc;
    int fd;

    fd = open(dev, O_RDONLY | O_NONBLOCK);
    if (fd < 0) {

    memset(scsi_serial, 0, sizeof (scsi_serial));
    rc = scsi_get_serial(fd, scsi_serial, 255);
    // scsi_serial[3] is the length of the serial number
    // scsi_serial[4] is serial number (raw, NOT null terminated)
    if (rc < 0) {
        printf("FAIL, rc=%d, errno=%dn", rc, errno);
    } else
    if (rc == 1) {
        printf("FAIL, rc=%d, drive doesn't report serial numbern", rc);
    } else {
        if (!scsi_serial[3]) {
            printf("Failed to retrieve serial for %sn", dev);
            return -1;
        printf("Serial Number: %.*sn", (size_t) scsi_serial[3], (char *) & scsi_serial[4]);

    return (EXIT_SUCCESS);

For the sake of completness i'll also provide the code to retrieve the serial number for ATA devices (hda, hdb ...). This will NOT work for USB devices.

#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <cctype>
#include <unistd.h>

int main(){
    struct hd_driveid *id;
    char *dev = "/dev/hda";
    int fd;

    fd = open(dev, O_RDONLY|O_NONBLOCK);
    if(fd < 0) {
        perror("cannot open");
    if (ioctl(fd, HDIO_GET_IDENTITY, id) < 0) {
        perror("ioctl error");
    } else {
        // if we want to retrieve only for removable drives use this branching
        if ((id->config & (1 << 7)) || (id->command_set_1 & 4)) {
            printf("Serial Number: %sn", id->serial_no);
        } else {
            perror("support not removable");
Monday, August 9, 2021
answered 4 Months ago

If the name stored by the PaDeviceInfo structure is sufficient, then you could just access the 'name' from the dict returned by get_device_info_by_index(), and then perhaps slice the information off the end:

import pyaudio

def getaudiodevices():
    p = pyaudio.PyAudio()
    for i in range(p.get_device_count()):
        print p.get_device_info_by_index(i).get('name')

gives me

HDA Intel HDMI: 0 (hw:0,3)
HDA Intel HDMI: 1 (hw:0,7)
HDA Intel HDMI: 2 (hw:0,8)
HDA Intel PCH: CS4208 Analog (hw:1,0)
HDA Intel PCH: CS4208 Digital (hw:1,1)

But this doesn't give you what you want with the default devices, the name seems to be stored as "default". In that case, executing "arecord -l" in Python can work, if that's what you're looking for. Of course, you can do the same thing for "aplay -l".

import os

def getaudiodevices():
    devices = os.popen("arecord -l")
    device_string =
    device_string = device_string.split("n")
    for line in device_string:
            if(line.find("card") != -1):
                print "hw:" + line[line.find("card")+5] + "," +


Monday, August 30, 2021
Martin R
answered 4 Months ago

I tried out the INF template that Daniel K suggested here with my own configurations:

;This .inf file is a modified version of the example INF provided
;in the Microsoft document:
;"How to Use WinUSB to Communicate with a USB Device"

Signature = "$Windows NT$"
Class = USBDevices
ClassGuid= {88BAE032-5A81-49f0-BC3D-A4FF138216D6}
Provider = %MFGNAME%
DriverVer=04/17/2014,    ;CAT file needed for a signed driver pacakage
; ========== Manufacturer/Models sections ===========
%MFGNAME% = MyDevice_WinUSB,NTx86,NTamd64

;  Vendor and Product ID Definitions
; When developing your custom USB device, the VID and PID used in the PC side
; application program and the firmware on the microcontroller must match.
; Modify the below lines to use your VID and PID.  Use the format as shown below.
; Note: One INF file can be used for multiple devices with different VID and PIDs.
; For each supported device, append ",USBVID_xxxx&PID_yyyy" to the end of the line.
; There is a maximum number of devices that can be supported per line however.
; If you append a large number of VID/PIDs to the end of the line, and get a:
; "The data area passed to a system call is too small." error when trying to install
; the INF, try removing some of the VIDs/PIDs.
%DESCRIPTION% =USB_Install, USBVID_0483&PID_5720

%DESCRIPTION% =USB_Install, USBVID_0483&PID_5720

;ClassInstall32 and ClassInstall_AddReg sections used to make new device manager category.


; =================== Installation ===================



DisplayName     = %WinUSB_SvcDesc%
ServiceType     = 1
StartType       = 3
ErrorControl    = 1
ServiceBinary   = %12%WinUSB.sys

KmdfService=WINUSB, WinUsb_Install



;When editing the GUID (the big hex number with dashes inside the squiggly 
;braces), make sure to write the intended PC application to use the same GUID.
;Otherwise the application won't be able to find the USB device properly.





; ================= Source Media Section =====================



; =================== Strings ===================

MFGNAME="ATP Industries Group" ; ManufacturerName
DESCRIPTION="TestCube" ; DeviceName
WinUSB_SvcDesc="WinUSB Device"
DISK_NAME="TestCubeDriver Installation Disk" ; DiskName
DEVICEMANAGERCATEGORY="Universal Serial Bus devices" ; ClassName

My device driver installed successfully and Device Manager reports that the device is working properly. I tried running my application and it's able to find my device and retrieve details about it. It all works now, and I can finally start working on the application-side of things.

Edit: Even though it's all working now, I have no idea what was wrong with the original template - could anyone please explain to me why the second template works and not the first?

Wednesday, November 17, 2021
answered 3 Weeks ago

You were quite near. You need to append to the list which is outside the loop

mxd_list = []
for top_dir, dir_list, obj_list in os.walk(top_path):
    mxd_list.extend([os.path.join(top_dir, obj) for obj in obj_list if obj.endswith('.mxd')])

The error is that - In every iteration of the outer for loop, the list comp would generate a list specific to that iteration only, thus you need to extend each of the list generated after every iteration to the outer variable, mxd_list.

Note - The [ are redundant in the sense that removing them would make the contents a generator expression. That is the the statement can be written as mxd_list.extend(os.path.join(top_dir, obj) for obj in obj_list if obj.endswith('.mxd')).

Another Way of doing it - Using glob.iglob

As Padraic mentions

mxd_list = []
for top_dir, dir_list, obj_list in os.walk(top_path):

Is a better way of doing it. But do not forget to import the module, i.e, from glob import iglob

Monday, November 22, 2021
answered 2 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :