vc++如何获取usb接口个数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vc++如何获取usb接口个数?相关的知识,希望对你有一定的参考价值。

笔记本上有三个usb插口,我想通过vc来检测出机器上usb插口的个数。我试了一下createfile和deviceiocontrol,打开\\.\HCDxx然后检测出driver key name和Hub name,顺序是通过枚举USB控制器->枚举此控制器上的USB HUB,这里我只想获取usb接口个数,所以就没有获取usb设备信息,但是通过测试,我发现我的笔记本和公司的台式机都只能打开HCD1\2 (台式机的usb接口有10个,我的电脑只有3个)。这是怎么回事呢?我又如何检测机器上的usb接口个数?(之前通过注册表查了串口接口个数,很简单,到了usb这里就不行了。。。)目前代码:
问题有更新 ,这是发在csdn上的同一个问题,请关注我3#的回帖问题,谢谢~
http://bbs.csdn.net/topics/391031218


   
#include "stdafx.h"
#include   <stdio.h>   
#include   <windows.h>   
#include   <setupapi.h>   
#include   <devguid.h>   
#pragma   comment(lib,   "setupapi")   
 
int   main(int   argc,   char*   argv[])   
   
    //   得到设备信息集   
    HDEVINFO   hDevInfo   =   SetupDiGetClassDevs(   
        (LPGUID)&GUID_DEVCLASS_PORTS,     
        NULL,     
        0,     
        DIGCF_PRESENT/*   |   DIGCF_ALLCLASSES*/);   
 
    if     (hDevInfo     ==     INVALID_HANDLE_VALUE)       
       
        printf("Error!   SetupDiGetClassDevs()   return   %d\\n",   GetLastError());   
        SetupDiDestroyDeviceInfoList(hDevInfo);   
        return     0;       
       
 
    TCHAR   szBuf[MAX_PATH];   
    SP_DEVINFO_DATA   spDevInfoData   =   sizeof(SP_DEVINFO_DATA);   
 
    //   开始列举设备   
    DWORD   i = 0;
    for   ( i   =   0;   SetupDiEnumDeviceInfo(hDevInfo,   i,   &spDevInfoData);   i++)   
       
        //   得到设备类描述   
        if   (   SetupDiGetClassDescription(   
            &spDevInfoData.ClassGuid,   
            szBuf,     
            MAX_PATH,     
            NULL)   )   
           
            _tprintf("\\n%03d   :   ClassDescription   =   %s\\n",   i,   szBuf);   
           
 
        //   得到设备实例的唯一标识ID(由注册表路径组成)   
        if   (   SetupDiGetDeviceInstanceId(   
            hDevInfo,   
            &spDevInfoData,   
            szBuf,   
            MAX_PATH,   
            NULL)   )   
           
            printf("%03d   :   InstanceId   =   %s\\n",   i,   szBuf);   
           
 
        //   得到设备名称   
        if   (   SetupDiGetDeviceRegistryProperty(   
            hDevInfo,   
            &spDevInfoData,   
            SPDRP_DEVICEDESC,   
            NULL,     
            (PBYTE)szBuf,   
            MAX_PATH,     
            NULL)   )   
           
            printf("%03d   :   DeviceDesc   =   %s\\n",   i,   szBuf);   
           
 
        //   得到设备型号   
        if   (   SetupDiGetDeviceRegistryProperty(   
            hDevInfo,   
            &spDevInfoData,   
            SPDRP_FRIENDLYNAME,   
            NULL,     
            (PBYTE)szBuf,   
            MAX_PATH,     
            NULL)   )   
           
            printf("%03d   :   FriendName   =   %s\\n",   i,   szBuf);   
           
 
        //   得到设备在注册表中的子路径   
        if   (   SetupDiGetDeviceRegistryProperty(   
            hDevInfo,   
            &spDevInfoData,   
            SPDRP_DRIVER,   
            NULL,     
            (PBYTE)szBuf,   
            MAX_PATH,     
            NULL)   )   
           
            printf("%03d   :   Regedit   Path   =   %s\\n",   i,   szBuf);   
           
 
       
 
    printf("\\nPort  count   =   %d\\n",   i);   
    getchar();   
 
    return   0;   

参考技术A

vc++如何获取usb接口个数:

#include <windows.h>  
#include <stdio.h>  
#include <Shlwapi.h>  
#include <conio.h>  
extern "C"   
    // Declare the C libraries used  
#include <setupapi.h>  // Must link in setupapi.lib  
#include <hidsdi.h>   // Must link in hid.lib  
  
  
  
  
static /*const*/ GUID GUID_DEVINTERFACE_USB_DEVICE =   
 0xA5DCBF10L, 0x6530, 0x11D2,  0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED  ;  
  
TCHAR * GetErrString(TCHAR *str, DWORD errcode)    
    
    LPVOID lpbuf;    
    if(FormatMessage(     
        FORMAT_MESSAGE_ALLOCATE_BUFFER |    
        FORMAT_MESSAGE_FROM_SYSTEM |     
        FORMAT_MESSAGE_IGNORE_INSERTS,    
        NULL,    
        errcode,    
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),    
        (LPTSTR) &lpbuf,    
        0,    
        NULL    
        ))    
        
        lstrcpy(str,(LPCWSTR)lpbuf);    
        LocalFree(lpbuf);    
        
  
    return str;    
    
  
int main(int argc, char* argv[])  
  
    char szTraceBuf[256];  
    // Get device interface info set handle for all devices attached to system  
    HDEVINFO hDevInfo = SetupDiGetClassDevs(  
        &GUID_DEVINTERFACE_USB_DEVICE, /* CONST GUID * ClassGuid - USB class GUID */  
        NULL, /* PCTSTR Enumerator */  
        NULL, /* HWND hwndParent */  
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE /* DWORD Flags */  
        );   
  
    if (hDevInfo == INVALID_HANDLE_VALUE)  
      
        sprintf(szTraceBuf, "SetupDiClassDevs() failed. GetLastError() " \\  
            "returns: 0x%x\\n", GetLastError());  
        OutputDebugStringA(szTraceBuf);  
        return 1;  
      
    sprintf(szTraceBuf, "Device info set handle for all devices attached to " \\  
        "system: 0x%x\\n", hDevInfo);  
    OutputDebugStringA(szTraceBuf);  
    // Retrieve a context structure for a device interface of a device   
    // information set.  
    DWORD dwIndex = 0;  
    SP_DEVICE_INTERFACE_DATA devInterfaceData;  
    ZeroMemory(&devInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));  
    devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);  
    BOOL bRet = FALSE;  
    ULONG  neededLength,requiredLength;    
    PSP_DEVICE_INTERFACE_DETAIL_DATA         ClassDeviceData;   
    HIDD_ATTRIBUTES   attributes;   
  
    while(TRUE)  
       
        bRet = SetupDiEnumDeviceInterfaces(  
            hDevInfo, /* HDEVINFO DeviceInfoSet */  
            NULL, /* PSP_DEVINFO_DATA DeviceInfoData */   
            &GUID_DEVINTERFACE_USB_DEVICE, /* CONST GUID * InterfaceClassGuid */  
            dwIndex,  
            &devInterfaceData /* PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData */  
            );  
        if (!bRet)  
          
            TCHAR buffer[1024];  
            TCHAR szTraceBuf[1024];  
            GetErrString(buffer,GetLastError());  
  
            wsprintf(szTraceBuf, L"SetupDiEnumDeviceInterfaces failed msg:%s",buffer);  
            OutputDebugStringW(szTraceBuf);  
  
            if (GetLastError() == ERROR_NO_MORE_ITEMS)  
              
                break;  
              
        else  
  
            //   发现一个HID设备,获取设备的详细信息   
            //   第一次调用SetupDiGetDeviceInterfaceDetail得到ClassDeviceData的大小,但返回错误   
            SetupDiGetDeviceInterfaceDetail(hDevInfo,&devInterfaceData,   
                NULL,0,&requiredLength,NULL);   
            neededLength                         =requiredLength;   
            ClassDeviceData                         =(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(neededLength);   
            ClassDeviceData-> cbSize   =sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);   
  
            //第二次调用SetupDiGetDeviceInterfaceDetail     
            //   使用 合适的neededLength.   
            if   (!SetupDiGetDeviceInterfaceDetail(hDevInfo,&devInterfaceData,   
                ClassDeviceData,neededLength,&requiredLength,NULL))   
               
                free(ClassDeviceData);   
                SetupDiDestroyDeviceInfoList(hDevInfo);           
                return   -1;   
               
            //   建立HID设备的句柄   
            HANDLE handle=CreateFile(ClassDeviceData-> DevicePath,   
                GENERIC_READ|GENERIC_WRITE,   
                FILE_SHARE_READ|FILE_SHARE_WRITE,   
                NULL,OPEN_EXISTING,0,NULL);   
            //   获取   attributes   以便得到Vendor   ID   和   Product   ID   
            HidD_GetAttributes(handle,&attributes);   
  
            TCHAR buffer[1024];  
  
            wsprintf(buffer,L"name:%s pid=%d vid=%d version=%d \\n",ClassDeviceData-> DevicePath,attributes.ProductID,attributes.VendorID,attributes.VersionNumber);  
            OutputDebugStringW(buffer);  
            CloseHandle(handle);           
  
            free(ClassDeviceData);   
  
          
  
        dwIndex++;    
      
  
    sprintf(szTraceBuf, "Number of device interface sets representing all " \\  
        "devices attached to system: %d\\n", dwIndex);  
    OutputDebugStringA(szTraceBuf);  
    SetupDiDestroyDeviceInfoList(hDevInfo);  
    getch();  
    return 0;  

参考技术B 这涉及到驱动方面的知识.建议下载WinSDK 关于vxd驱动方面的知识 参考技术C 我也写过,然后一个都没有找出来。你可以把你的全部代码给我观摩一下嘛。能找到的例子太少了。
拜托。小白急需拯救。
还有我私信你了。

VC++获取电脑的各个磁盘盘符及容量信息(附源码)

目录

1、调用GetLogicalDrives接口获取逻辑磁盘个数

2、调用GetLogicalDriveStrings接口获取磁盘盘符列表字串

3、从磁盘列表字串中解析出每个磁盘盘符并获取对应的磁盘类型

4、调用GetDiskFreeSpaceEx接口获取磁盘的容量信息

5、完整代码展示


       有时我们需要获取电脑上所有磁盘及容量信息,本文将详细讲述如何调用系统API函数来获取这些信息。

1、调用GetLogicalDrives接口获取逻辑磁盘个数

      首先,我们先调用系统API接口GetLogicalDrives获取逻辑磁盘的个数,该函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的逻辑磁盘,1为磁盘,0为非磁盘,所以我通过遍历该函数返回的32位整型数值的每一个bit去得到当前电脑上的逻辑磁盘个数。相关代码如下所示:

int nDiskCount = 0;
// GetLogicalDrives函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的磁盘,1为磁盘,0为非磁盘
DWORD nDiskMask = GetLogicalDrives();
while ( nDiskMask )

    // 判断最低位是否为1
    if ( nDiskMask & 1 )
    
        ++nDiskCount;
    

    // 进行右移操作,检查最低位是否为1
    nDiskMask = nDiskMask >> 1;

2、调用GetLogicalDriveStrings接口获取磁盘盘符列表字串

       调用系统API接口GetLogicalDriveStrings获取的磁盘符号列表字串的格式为:C:\\\\0D:\\\\0E:\\0(注意此处的\\0是分隔符,\\0是一个字符),此处讲的字串不是我们平时用的字符串,因为字符串是以\\0结尾的,而此处获取的磁盘符号列表字串中是以\\0为分隔符的。

       我们在调用GetLogicalDriveStrings时,最开始给该函数的第一个参数传0,这样GetLogicalDriveStrings返回的就是用来存放磁盘符号列表字串所需要的buffer长度。然后我们用这个长度值去创建buffer,然后再调用GetLogicalDriveStrings函数接口即可获取。相关代码如下:

// 先传入0,获取装载磁盘字串的缓冲区长度
int nDiskStringsLen = GetLogicalDriveStrings( 0, NULL );
//通过获取装载磁盘字串的缓冲区长度,去创建缓冲区buffer
TCHAR* szDiskStringsBuf = new TCHAR[nDiskStringsLen+1];
memset( szDiskStringsBuf, 0, (nDiskStringsLen+1)*sizeof(TCHAR) );
// 用创建的buffer去获取磁盘符号字串
GetLogicalDriveStrings( nDiskStringsLen, (LPTSTR)szDiskStringsBuf );

3、从磁盘列表字串中解析出每个磁盘盘符并获取对应的磁盘类型

       获取的磁盘符号列表字串的格式为:C:\\\\0D:\\\\0E:\\0,我们按照这个格式,每四个字节就包含了一个磁盘盘符,按照这个规律去截取,然后再调用系统API接口GetDriveType,来获取该磁盘的类型。常见的磁盘类型有硬盘、移动式磁盘(移动硬盘和U盘)、光驱、网络磁盘和虚拟RAM磁盘等。相关的代码如下所示:

// 磁盘符号列表串是这样子的:C:\\NULLD:\\NULLE:\\NULL(其中NULL为\\0),所以每个磁盘符号占用4个TCHAR
for (int i = 0; i < nDiskStringsLen / 4; ++i)

// 考虑到程序是Unicode宽字节的版本,所以可能会用到wcout,所以用UNICODE宏判断一下
#ifdef UNICODE
    wcout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#else
    cout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#endif

    nDiskType = GetDriveType( szDiskStringsBuf + i*4 );
    if ( nDiskType == DRIVE_FIXED )
    
        cout << "硬盘";
    
    else if ( nDiskType == DRIVE_REMOVABLE )
    
        cout << "移动式磁盘";
    
    else if ( nDiskType == DRIVE_CDROM )
    
        cout << "光驱";
    
    else if ( nDiskType == DRIVE_REMOTE )
    
        cout << "网络磁盘";
    
    else if ( nDiskType == DRIVE_RAMDISK )
    
        cout << "虚拟RAM磁盘";
    
    else if ( nDiskType == DRIVE_UNKNOWN )
    
        cout << "未知设备";
    

    //......(此处省略代码)

4、调用GetDiskFreeSpaceEx接口获取磁盘的容量信息

       我们拿到盘符后,然后就可以调用系统API接口GetDiskFreeSpaceEx去获取对应盘的容量信息了,包含总的容量和可用容量信息。

unsigned _int64 u64FreeBytesAvailableToCaller = 0;
unsigned _int64 u64TotalNumberOfBytes = 0;
unsigned _int64 u64TotalNumberOfFreeBytes = 0;

TCHAR szhRootPath[64] =  0 ;
_stprintf( szhRootPath, _T("%c:\\\\"), szDiskStringsBuf[nDiskStartIdx] );
// 调用GetDiskFreeSpaceEx函数获取磁盘的容量信息
BOOL bRet = GetDiskFreeSpaceEx( szhRootPath, (PULARGE_INTEGER)&u64FreeBytesAvailableToCaller,
(PULARGE_INTEGER)&u64TotalNumberOfBytes, (PULARGE_INTEGER)&u64TotalNumberOfFreeBytes );
if (bRet)

    tstring strTotalSizeText = GetSizeDescText( u64TotalNumberOfBytes );
    tstring strTotalFreeSizeText = GetSizeDescText( u64TotalNumberOfFreeBytes );

#ifdef UNICODE
    wcout << "   磁盘总容量:" << strTotalSizeText.c_str();
    wcout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#else
    cout << "   磁盘总容量:" << strTotalSizeText.c_str();
    cout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#endif

else

    cout << "  获取容量信息失败";

       这个地方有几点需要说明一下。为了方便操作字符串,我们使用了C++的string类,为了兼容Unicode宽字节,我们还使用了wstring,所以我们特意定义了一个tstring类型,如下所示:

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

Unicode宽字节下tstring对应的就是宽字节版本的wstring,在ANSI窄字节下对应窄字节版本的string。工程到底使用的是Unicode宽字节还是ANSI窄字节,是在工程属性中设定的,如下:

        此外,上述代码中缓冲区buffer使用了支持Unicode的TCHAR类型,该类型对应的定义为:

#ifdef _UNICODE
typedef WCHAR TCHAR, *PTCHAR;
#else
typedef char TCHAR, *PTCHAR;
#endif

所以我们在使用cout打印信息时,也使用了wcoutcout,即Unicode下用wcout、ANSI下用cout。另外,我们在显示磁盘容量大小时,我们实现了一个根据实际容量大小选择合适单位来显示,比如B、KB、MB、GB、TB等,函数内部实现如下:

tstring GetSizeDescText( unsigned __int64 u64Size )

    TCHAR* typeText[] = 
    
        _T("B"),
        _T("KB"),
        _T("MB"),
        _T("GB"),
        _T("TB")
    ;

    int nArrSize = 5; // 数组typeText大小,要严格和typeText对应起来

    int index = 0; // typeText数组索引
    double douSize = (double)u64Size;
    while( douSize >= 1024 && index < nArrSize )
    
        douSize /= 1024.0;
        index++;
    

    tstring strSizeText;
    TCHAR szSizeNum[256] =  0 ;
    _stprintf( szSizeNum, _T("%0.1f"), douSize ); // 保留一位小数点
    strSizeText = szSizeNum;
    strSizeText += typeText[index];
    return strSizeText;

5、完整代码展示

       可以用Visual Studio创建一个控制台工程,然后将下面给出的代码拷贝到工程中运行即可。完整代码如下:

#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

tstring GetSizeDescText( unsigned __int64 u64Size )

    TCHAR* typeText[] = 
    
        _T("B"),
        _T("KB"),
        _T("MB"),
        _T("GB"),
        _T("TB")
    ;

    int nArrSize = 5; // 数组typeText大小,要严格和typeText对应起来

    int index = 0; // typeText数组索引
    double douSize = (double)u64Size;
    while( douSize >= 1024 && index < nArrSize )
    
        douSize /= 1024.0;
        index++;
    

    tstring strSizeText;
    TCHAR szSizeNum[256] =  0 ;
    _stprintf( szSizeNum, _T("%0.1f"), douSize ); // 保留一位小数点
    strSizeText = szSizeNum;
    strSizeText += typeText[index];
    return strSizeText;


int _tmain(int argc, _TCHAR* argv[])

    // 1、先获取逻辑磁盘的个数
    int nDiskCount = 0;
    // GetLogicalDrives函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的磁盘,1为磁盘,0为非磁盘
    DWORD nDiskMask = GetLogicalDrives();
    while ( nDiskMask )
    
        // 判断最低位是否为1
        if ( nDiskMask & 1 )
        
            ++nDiskCount;
        

        // 进行右移操作,检查最低位是否为1
        nDiskMask = nDiskMask >> 1;
    
    
    cout << endl;
    cout << "逻辑磁盘数量:" << nDiskCount << endl;
    
    // 2、获取磁盘符号列表串:C:\\NULLD:\\NULLE:\\NULL(其中NULL为\\0)
    // 先传入0,获取装载磁盘字串的缓冲区长度
    int nDiskStringsLen = GetLogicalDriveStrings( 0, NULL );
    //通过获取装载磁盘字串的缓冲区长度,去创建缓冲区buffer
    TCHAR* szDiskStringsBuf = new TCHAR[nDiskStringsLen+1];
    memset( szDiskStringsBuf, 0, (nDiskStringsLen+1)*sizeof(TCHAR) );
    // 用创建的buffer去获取磁盘符号字串
    GetLogicalDriveStrings( nDiskStringsLen, (LPTSTR)szDiskStringsBuf );

    int nDiskType = 0;
    int nDiskStartIdx = 0;
    unsigned _int64 u64FreeBytesAvailableToCaller = 0;
    unsigned _int64 u64TotalNumberOfBytes = 0;
    unsigned _int64 u64TotalNumberOfFreeBytes = 0;

    // 3、从磁盘符号列表串中解析出每个盘符,并获取每个盘的容量
    // 磁盘符号列表串是这样子的:C:\\NULLD:\\NULLE:\\NULL(其中NULL为\\0),所以每个磁盘符号占用4个TCHAR
    for (int i = 0; i < nDiskStringsLen / 4; ++i)
    
        // 考虑到程序是Unicode宽字节的版本,所以可能会用到wcout,所以用UNICODE宏判断一下
#ifdef UNICODE
        wcout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#else
        cout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#endif

        nDiskType = GetDriveType( szDiskStringsBuf + i*4 );
        if ( nDiskType == DRIVE_FIXED )
        
            cout << "硬盘";
        
        else if ( nDiskType == DRIVE_REMOVABLE )
        
            cout << "移动式磁盘";
        
        else if ( nDiskType == DRIVE_CDROM )
        
            cout << "光驱";
        
        else if ( nDiskType == DRIVE_REMOTE )
        
            cout << "网络磁盘";
        
        else if ( nDiskType == DRIVE_RAMDISK )
        
            cout << "虚拟RAM磁盘";
        
        else if ( nDiskType == DRIVE_UNKNOWN )
        
            cout << "未知设备";
        
    
        TCHAR szhRootPath[64] =  0 ;
        _stprintf( szhRootPath, _T("%c:\\\\"), szDiskStringsBuf[nDiskStartIdx] );
        // 调用GetDiskFreeSpaceEx函数获取磁盘的容量信息
        BOOL bRet = GetDiskFreeSpaceEx( szhRootPath, (PULARGE_INTEGER)&u64FreeBytesAvailableToCaller,
            (PULARGE_INTEGER)&u64TotalNumberOfBytes, (PULARGE_INTEGER)&u64TotalNumberOfFreeBytes );
        if (bRet)
        
            //cout << "   磁盘总容量:" << (float)u64TotalNumberOfBytes/1024/1024 /1024 << " G";
            //cout << "   磁盘可用容量:" << (float)u64TotalNumberOfFreeBytes/1024/1024/1024 << " G";

            tstring strTotalSizeText = GetSizeDescText( u64TotalNumberOfBytes );
            tstring strTotalFreeSizeText = GetSizeDescText( u64TotalNumberOfFreeBytes );

#ifdef UNICODE
            wcout << "   磁盘总容量:" << strTotalSizeText.c_str();
            wcout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#else
            cout << "   磁盘总容量:" << strTotalSizeText.c_str();
            cout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#endif

        
        else
        
            cout << "  获取容量信息失败";
        

        cout << endl;
        nDiskStartIdx += 4;
    

    cout << endl;
    system("pause");

我机器的运行结果是:(机器上插入了一个U盘)

以上是关于vc++如何获取usb接口个数?的主要内容,如果未能解决你的问题,请参考以下文章

怎么从接口里获取数据、、

VC++获取电脑的各个磁盘盘符及容量信息(附源码)

ubuntu 下如何获取USB接口相机的uri路径

从 Arduino Yun 上的 USB 接口获取 MIDI 音符

用VC怎样获取USB摄像头图像,最好有代码

浅析usbhid驱动如何源源不断的获取usb鼠标