读取U盘 PID,VID,序列号等信息.

本文介绍了一种通过编程手段获取U盘PID和VID信息的方法。首先通过枚举系统中的磁盘来确定U盘盘符,然后利用Windows API函数获取U盘的详细信息,包括PID、VID和序列号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为工作需要,要写一个读取U盘PID,VID信息的程序,在网上找了很久都没有发现有相关的资料.相关的工作也搁置了很久,真是亏对公司^_^

  还好终于让我慢慢揣摩出来一点端倪,在这分享一下.其实用DDK会比较容易得到.但是DDK编译设置又比较麻烦,而且我是要用BCB开发,所以也先不往那方面发展了.现在就开始讲讲.

1.获取U盘盘符.

这个比较简单,首先列举一下系统的磁盘.如果属性是DRIVE_REMOVABLE那么就是可移动磁盘.排除软盘,那么剩下的就是U盘咯.

int __fastcall C_BA580_PATH::GetUsbDevice(AnsiString* strUsbDriverName)
{
        char lpBuffer[MAX_DRIVER_STRING_LENGHT];
        char*lpSingleDevice;

        DWORD nBufferLength = MAX_DRIVER_STRING_LENGHT;
        DWORD dwSignleDeviceBufferIndex =0, dwDeviceNum =0;

        lpSingleDevice  = (char*)malloc(sizeof(char)* MAX_DRIVER_STRING_LENGHT);
        if(lpSingleDevice == NULL)
        {
                ShowMessage("系统分配内存错误");
                return 0;
        }
        memset(lpSingleDevice,0x0,MAX_DRIVER_STRING_LENGHT);
        memset(lpBuffer,0x0,MAX_DRIVER_STRING_LENGHT);

        nBufferLength = GetLogicalDriveStrings(nBufferLength,lpBuffer); //列举盘符

        for(DWORD i =0; i< nBufferLength; i++)
        {
                if(lpBuffer[i] != 0x00)       //分离各个离盘符
                {
                        lpSingleDevice[dwSignleDeviceBufferIndex] = lpBuffer[i];
                        dwSignleDeviceBufferIndex++;
                        continue;
                }
                lpSingleDevice[dwSignleDeviceBufferIndex]  = 0x0;
                dwSignleDeviceBufferIndex = 0;
                if(*lpSingleDevice == 'A')  //A盘 不需要
                        continue;
                if(GetDriveType(lpSingleDevice) == DRIVE_REMOVABLE)   //获取移动磁盘
                {
                        strUsbDriverName[dwDeviceNum] = lpSingleDevice ;
                        dwDeviceNum++;
                }

        }
        free(lpSingleDevice);
        return dwDeviceNum;
}

2.获取PID,UID,序列号信息

int CUSBPortDlg::GetDevicePath(LPGUID lpGuid, LPTSTR* pszDevicePath)
{
    HDEVINFO hDevInfoSet;    //设备信息集句柄;
    SP_DEVICE_INTERFACE_DATA ifdata;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
    int nCount;
    BOOL bResult;
 LPGUID UsbClassGuid;
 CHANGER_PRODUCT_DATA ProductBuffer;
 unsigned long BytesReturned;
 
 UsbClassGuid = (LPGUID)malloc(sizeof(GUID));
 UsbClassGuid->Data1 = 0xa5dcbf10L;
 UsbClassGuid->Data2 = 0x6530;
 UsbClassGuid->Data3 = 0x11d2;
 UsbClassGuid->Data4[0] = 0x90;
 UsbClassGuid->Data4[1] = 0x1F;
 UsbClassGuid->Data4[2] = 0x00;
 UsbClassGuid->Data4[3] = 0xC0;
 UsbClassGuid->Data4[4] = 0x4F;
 UsbClassGuid->Data4[5] = 0xB9;
 UsbClassGuid->Data4[6] = 0x51;
 UsbClassGuid->Data4[7] = 0xED; 

    // 取得一个该GUID相关的设备信息集句柄
    hDevInfoSet = SetupDiGetClassDevs(UsbClassGuid,     // class GUID
        NULL,                    // 无关键字
        NULL,                    // 不指定父窗口句柄
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);    // 目前存在的设备
 
    // 失败...
    if (hDevInfoSet == INVALID_HANDLE_VALUE)
    {
        return 0;
    }
 
    // 申请设备接口数据空间
    pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
 
    pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
    nCount = 0;
    bResult = TRUE;
 
    // 设备序号=0,1,2... 逐一测试设备接口,到失败为止
    while (bResult)
    {
        ifdata.cbSize = sizeof(ifdata);
  
        // 枚举符合该GUID的设备接口
        bResult = ::SetupDiEnumDeviceInterfaces(
            hDevInfoSet,     // 设备信息集句柄
            NULL,            // 不需额外的设备描述
            UsbClassGuid,          // GUID
            (ULONG)nCount,   // 设备信息集里的设备序号
            &ifdata);        // 设备接口信息
  
        if (bResult)
        {
            // 取得该设备接口的细节(设备路径)
            bResult = SetupDiGetInterfaceDeviceDetail(
                hDevInfoSet,    // 设备信息集句柄
                &ifdata,        // 设备接口信息
                pDetail,        // 设备接口细节(设备路径)
                INTERFACE_DETAIL_SIZE,   // 输出缓冲区大小
                NULL,           // 不需计算输出缓冲区大小(直接用设定值)
                NULL);          // 不需额外的设备描述
            if (bResult)
            {
                // 复制设备路径到输出缓冲区
                ::strcpy(pszDevicePath[nCount], pDetail->DevicePath);
    // 调整计数值
                nCount++;
            }
        }
    }
    // 释放设备接口数据空间
    ::GlobalFree(pDetail);
    // 关闭设备信息集句柄
    ::SetupDiDestroyDeviceInfoList(hDevInfoSet);
    return nCount;
}

pDetail->DevicePath 将是一串像"//?/usb#vid_0537&pid_a703#192b0c00048a#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"的字符串,看到没有VID=0537,PID=A703,serial=192b0c00048a

所以分离这串字符串就可以得到你想要的信息了.至于要与盘符相对应上的PID VID我还没有找到在SDK实现的方法

不过慢慢会找到的.

參考:
Linux读取U或者移动硬序列号并获取U或者移动硬分区名。基本原理如下: 当有外置 USB 插入的时候,会产生 /proc/scsi/usb-storage 目录,并在其中产生数字文件(形如 1 2 3 4),此文件存储了设备相关信息。 相应的 /sys/class/scsi_device/ 目录中会有 scsi 设备的目录(ide 硬默认无子目录,sata硬默认有子目录),以数字开头(形如 1:0:0:0 2:0:0:0) 这个数字与前面 /proc/scsi/usb-storage目录中的相对应,子目录表示sata硬。比如 /sys/class/scsi_device/2:0:0:0/device/block 中有USB设备,从该目录下得到U或者移动硬的分区名,比如sda1。 该demo实现了上述过程,先检查 /proc/scsi/usb-storage 目录,看是否有u或者移动硬接入,如果有则读取u或者移动硬序列号,然后在/sys/class/scsi_device/目录下逐级查找,直到找到u或者移动硬的分区。 完整代码,可直接编译和测试,嵌入式环境下也是适应的。 在linux测试如下,id表示序列号,sdb1表示是分区名称: # ./a.out udisk dev num:0 udisk id:055CE21B ret:0 dev num:0 found dir:0:0:0:1 found dev dir:0:0:0:1,full path:/sys/class/scsi_device/0:0:0:1 sub founction found dir:sda found sd device dir:sda,full path:/sys/class/scsi_device/0:0:0:1/device/block/sda found dir:0:0:0:2 found dev dir:0:0:0:2,full path:/sys/class/scsi_device/0:0:0:2 sub founction found dir:sdb found sd device dir:sdb,full path:/sys/class/scsi_device/0:0:0:2/device/block/sdb found sd sub device dir:sdb1 found dir:0:0:0:0 found dev dir:0:0:0:0,full path:/sys/class/scsi_device/0:0:0:0 sub funciton Open Directory /sys/class/scsi_device/0:0:0:0/device/block Error:No such file or directory get name return:0,disk name:sdb1 # 因为有的USB设备会有好几个,比如把CD和U集成到一起,就会出现上面的情况,有多个子目录去查找。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值