列出具有指定 VID 和 PID 的 USB 设备,无需使用 Windows 驱动程序套件

问题描述 投票:0回答:4

有没有一种方法可以在 Windows 上查找具有指定 VID 和 PID 的 USB 设备,而无需调用 WDK 函数?

visual-c++ usb
4个回答
8
投票

这是郭彦超代码的简化版:

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
    }
}

5
投票

下面的代码就可以解决问题:

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;
    }
}

1
投票

是的,可以,您在 user32.dll 和 setuapi.dll 中拥有 Win32 API 中所有必需的功能。这是一个小 C# 示例:

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;
    }

而包装代码是:

   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);
}

希望对你有帮助,你应该快速将其翻译成Visual C++


0
投票
using System;
using System.Management;  // Add System.Management via NuGet
using System.Text.RegularExpressions;
using System.Linq;

namespace HIDInfoRetriever
{
    class Program
    {
        static void Main(string[] args)
        {
            // Define the column headers
            string[] headers = { "Device Name", "Device ID", "Manufacturer", "Description", "Vendor ID (VID)", "Product ID (PID)", "GUID" };

            // Find the maximum width for each column
            int[] columnWidths = headers.Select(h => h.Length).ToArray();

            // Query WMI for connected devices
            var searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_PnPEntity WHERE Status = 'OK'");
            var devices = searcher.Get();

            // Prepare a list to store device information rows
            var rows = devices.Cast<ManagementObject>()
                              .Where(device => device["Name"] != null && device["Name"].ToString().Contains("HID"))
                              .Select(device =>
                              {
                                  var row = new string[7];

                                  // Populate device information
                                  row[0] = device["Name"]?.ToString() ?? "Unknown";
                                  row[1] = device["DeviceID"]?.ToString() ?? "Unknown";
                                  row[2] = device["Manufacturer"]?.ToString() ?? "Unknown";
                                  row[3] = device["Description"]?.ToString() ?? "Unknown";

                                  // Extract Vendor ID (VID) and Product ID (PID)
                                  string hardwareIds = device["DeviceID"]?.ToString();
                                  if (!string.IsNullOrEmpty(hardwareIds))
                                  {
                                      var match = Regex.Match(hardwareIds, @"VID_([0-9A-F]{4})&PID_([0-9A-F]{4})");
                                      row[4] = match.Success ? match.Groups[1].Value : "Unknown";  // Vendor ID (VID)
                                      row[5] = match.Success ? match.Groups[2].Value : "Unknown";  // Product ID (PID)
                                  }
                                  else
                                  {
                                      row[4] = "Unknown";
                                      row[5] = "Unknown";
                                  }

                                  // Retrieve GUID
                                  row[6] = device["ClassGuid"]?.ToString() ?? "Unknown";

                                  // Update column widths based on content
                                  for (int i = 0; i < row.Length; i++)
                                  {
                                      columnWidths[i] = Math.Max(columnWidths[i], row[i].Length);
                                  }

                                  return row;
                              })
                              .OrderBy(row => row[4]) // Sort by Vendor ID (VID)
                              .ThenBy(row => row[5])  // Then by Product ID (PID)
                              .ToList();

            // Print the table headers
            PrintRow(headers, columnWidths);

            // Print a line separator under the headers
            Console.WriteLine(new string('-', columnWidths.Sum() + headers.Length * 3 - 1));

            // Print all device rows
            foreach (var row in rows)
            {
                PrintRow(row, columnWidths);
            }

            Console.WriteLine("Device scan complete.");
            Console.ReadLine();
        }

        // Method to print a row in the table
        static void PrintRow(string[] row, int[] columnWidths)
        {
            for (int i = 0; i < row.Length; i++)
            {
                string formattedColumn = row[i].PadRight(columnWidths[i]);
                if (i == row.Length - 1)
                    Console.Write(formattedColumn);
                else
                    Console.Write(formattedColumn + " | ");
            }
            Console.WriteLine();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.