list USB device with specified VID and PID without using Windows driver Kit

后端 未结 3 1753
半阙折子戏
半阙折子戏 2021-02-09 14:04

is there a way to find a USB device with specified VID and PID on windows without involve calling to WDK functions?

相关标签:
3条回答
  • 2021-02-09 14:29

    Yes you can, you have all the necessary functions in Win32 API in user32.dll and setuapi.dll. This is a little C# sample:

    internal static bool FindUsbDevice(string vendorId, string productId, 
            ref string deviceDesc, ref string deviceInstanceId, ref Guid classId)
        {
            bool returnValue = false;
            string enumeratorClass = "USB";
            IntPtr szClass = Marshal.StringToHGlobalAuto(enumeratorClass);
            Guid classGuid = Guid.Empty;
            IntPtr deviceInfoSet = new System.IntPtr();
    
            try
            {
                deviceInfoSet = DeviceManagement.SetupDiGetClassDevs(ref classGuid, szClass, IntPtr.Zero,
                    DeviceManagement.DIGCF_ALLCLASSES | DeviceManagement.DIGCF_PRESENT);
    
                DeviceManagement.SP_DEVINFO_DATA spDevInfoData = new DeviceManagement.SP_DEVINFO_DATA();
                spDevInfoData.cbSize = Marshal.SizeOf(spDevInfoData);
    
                for (int i = 0; DeviceManagement.SetupDiEnumDeviceInfo(deviceInfoSet, i, ref spDevInfoData); i++)
                {
                    int nSize = 0;
                    string DeviceInstanceId = new string('0', 259);
                    IntPtr ptrDeviceInstanceId = Marshal.StringToHGlobalAuto(DeviceInstanceId);
    
                    if (!DeviceManagement.SetupDiGetDeviceInstanceId(deviceInfoSet, ref spDevInfoData, ptrDeviceInstanceId,
                        DeviceInstanceId.Length, ref nSize))
                    {
                        Console.WriteLine("SetupDiGetDeviceInstanceId() error");
                        continue;
                    }
                    DeviceInstanceId = Marshal.PtrToStringAnsi(ptrDeviceInstanceId);
    
                    if (!DeviceInstanceId.Contains(string.Format("USB\\VID_{0}&PID_{1}", vendorId, productId)))
                        continue;
    
                    returnValue = true;
                    deviceInstanceId = DeviceInstanceId;
                    classId = spDevInfoData.ClassGuid;
    
                    int DataT = 0;
                    string buffer = new string('0', 259);
                    IntPtr pBuffer = Marshal.StringToHGlobalAuto(buffer);
                    int bufferSize = 259;
    
                    if (!DeviceManagement.SetupDiGetDeviceRegistryProperty(
                        deviceInfoSet, ref spDevInfoData, DeviceManagement.SPDRP_DEVICEDESC,
                        ref DataT, pBuffer, bufferSize, ref bufferSize))
                    {
                        if (Marshal.GetLastWin32Error() == DeviceManagement.ERROR_INVALID_DATA)
                            Debug.WriteLine("Error invalid data");
                        else
                            Debug.WriteLine("error");
                    }
                    else
                    {
                        buffer = Marshal.PtrToStringAnsi(pBuffer, bufferSize);
                        deviceDesc = buffer;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                DeviceManagement.SetupDiDestroyDeviceInfoList(deviceInfoSet);
            }
            return returnValue;
        }
    

    while the wrapper code is:

       public sealed partial class DeviceManagement
    {
        ///<summary >
        // API declarations relating to device management (SetupDixxx and 
        // RegisterDeviceNotification functions).   
        /// </summary>
    
        // from dbt.h
    
        internal const Int32 DBT_DEVICEARRIVAL = 0X8000;
        internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004;
        internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5;
        internal const Int32 DBT_DEVTYP_HANDLE = 6;
        internal const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
        internal const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 1;
        internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0;
        internal const Int32 WM_DEVICECHANGE = 0X219;
    
        // from setupapi.h
    
        internal const Int32 DIGCF_PRESENT = 2;
        internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
        internal const Int32 DIGCF_ALLCLASSES = 0x4;
        internal const Int32 SPDRP_FRIENDLYNAME = 0xC;
        internal const Int32 SPDRP_DEVICEDESC = 0x0;
        internal const Int32 SPDRP_CLASSGUID = 0x8;
    
        // from WinError.h
        internal const Int32 ERROR_INSUFFICIENT_BUFFER = 122;
        internal const Int32 ERROR_INVALID_DATA = 13;
    
        // Two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure.
    
        // Use this one in the call to RegisterDeviceNotification() and
        // in checking dbch_devicetype in a DEV_BROADCAST_HDR structure:
    
        [StructLayout(LayoutKind.Sequential)]
        internal class DEV_BROADCAST_DEVICEINTERFACE
        {
            internal Int32 dbcc_size;
            internal Int32 dbcc_devicetype;
            internal Int32 dbcc_reserved;
            internal Guid dbcc_classguid;
            internal Int16 dbcc_name;
        }
    
        // Use this to read the dbcc_name String and classguid:
    
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal class DEV_BROADCAST_DEVICEINTERFACE_1
        {
            internal Int32 dbcc_size;
            internal Int32 dbcc_devicetype;
            internal Int32 dbcc_reserved;
            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
            internal Byte[] dbcc_classguid;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
            internal Char[] dbcc_name;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        internal class DEV_BROADCAST_HDR
        {
            internal Int32 dbch_size;
            internal Int32 dbch_devicetype;
            internal Int32 dbch_reserved;
        }
    
        internal struct SP_DEVICE_INTERFACE_DATA
        {
            internal Int32 cbSize;
            internal System.Guid InterfaceClassGuid;
            internal Int32 Flags;
            internal IntPtr Reserved;
        }
    
        internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
        {
            internal Int32 cbSize;
            internal String DevicePath;
        }
    
        internal struct SP_DEVINFO_DATA
        {
            internal Int32 cbSize;
            internal System.Guid ClassGuid;
            internal Int32 DevInst;
            internal Int32 Reserved;
        }
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, IntPtr DeviceInstanceId, int DeviceInstanceIdSize, ref int RequiredSize);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, int Property, ref int PropertyRegDataType, IntPtr PropertyBuffer, int PropertyBufferSize, ref int RequiredSize);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern Int32 SetupDiCreateDeviceInfoList(ref System.Guid ClassGuid, Int32 hwndParent);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
    
        [DllImport("setupapi.dll", SetLastError = true)]
        internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
    
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
    
        [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
    
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
    }
    

    Hope it helps, you should quickly translate it into Visual C++

    0 讨论(0)
  • 2021-02-09 14:31

    The code below will do the trick:

    static const char dongleVid[] = {'1', '2', '3', '4', '\0'};
    static const char donglePid[] = {'5', '6', '7', '8', '\0'};
    static const LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};
    
    const std::string requiredVid = boost::to_upper_copy(std::string(arPrefix[0]) + std::string(dongleVid));
    const std::string requiredPid = boost::to_upper_copy(std::string(arPrefix[1]) + std::string(donglePid));
    unsigned i, j;
    
    DWORD dwSize, dwPropertyRegDataType;
    OSVERSIONINFO osvi;
    CONFIGRET r;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    
    TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];
    TCHAR szDesc[1024];
    LPTSTR pszToken, pszNextToken;
    TCHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];
    
    #ifdef UNICODE
    FN_SetupDiGetDeviceProperty fn_SetupDiGetDeviceProperty = (FN_SetupDiGetDeviceProperty)
        GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");
    #else
    FN_SetupDiGetDeviceProperty fn_SetupDiGetDeviceProperty = (FN_SetupDiGetDeviceProperty)
        GetProcAddress(GetModuleHandle(TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyA");
    #endif
    
    // List all connected USB devices
    hDevInfo = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT|DIGCF_ALLCLASSES);
    if (hDevInfo == INVALID_HANDLE_VALUE)
    {
        return false;
    }
    // Find the ones that are driverless
    for (i = 0; ; i++)
    {
        DeviceInfoData.cbSize = sizeof(DeviceInfoData);
        if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
        {
            break;
        }
    
        r = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0);
        if (r != CR_SUCCESS)
        {
            continue;
        }
    
        SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,
                                              &dwPropertyRegDataType, (BYTE*)szDesc,
                                              sizeof(szDesc),   // The size, in bytes
                                              &dwSize);
    
        // Retreive the device description as reported by the device itself
        memset(&osvi, 0, sizeof(OSVERSIONINFO));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    
        pszToken = _tcstok_s(szDeviceInstanceID , TEXT("\\#&"), &pszNextToken);
        szVid[0] = TEXT('\0');
        szPid[0] = TEXT('\0');
        szMi[0] = TEXT('\0');
        while (pszToken != NULL)
        {
            for (j = 0; j < 3; j++)
            {
                if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0)
                {
                    switch (j)
                    {
                        case 0:
                            _tcscpy_s(szVid, ARRAY_SIZE(szVid), pszToken);
                            break;
                        case 1:
                            _tcscpy_s(szPid, ARRAY_SIZE(szPid), pszToken);
                            break;
                        case 2:
                            _tcscpy_s(szMi, ARRAY_SIZE(szMi), pszToken);
                            break;
                        default:
                            break;
                    }
                }
            }
            pszToken = _tcstok_s(NULL, TEXT("\\#&"), &pszNextToken);
        }
    
    
        std::string foundVid = boost::to_upper_copy(std::string(szVid));
        std::string foundPid = boost::to_upper_copy(std::string(szPid));
    
        if (requiredVid == foundVid && requiredPid == foundPid)
        {
            return true;
        }
    }
    
    0 讨论(0)
  • 2021-02-09 14:33

    Here's a simplified version of Guo Yanchao's code:

    unsigned index;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    TCHAR HardwareID[1024];
    
    // List all connected USB devices
    hDevInfo = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
    for (index = 0; ; index++) {
        DeviceInfoData.cbSize = sizeof(DeviceInfoData);
        if (!SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData)) {
            return false;     // no match
        }
    
        SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_HARDWAREID, NULL, (BYTE*)HardwareID, sizeof(HardwareID), NULL);
    
        if (_tcsstr(HardwareID, _T("VID_1234&PID_5678"))) {
            return true;     // match
        }
    }
    
    0 讨论(0)
提交回复
热议问题