is there a way to find a USB device with specified VID and PID on windows without involve calling to WDK functions?
list USB device with specified VID and PID without using Windows driver Kit
Asked Answered
Use the SetupAPI: msdn.microsoft.com/en-us/library/ff550897%28v=VS.85%29.aspx –
Navarra
possible duplicate of How to list all attached USB devices in Visual C++ –
Poltroonery
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;
}
}
You never actually use the OSVERSIONINFO variable you declare. –
Transmundane
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
}
}
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;
}
}
You never actually use the OSVERSIONINFO variable you declare. –
Transmundane
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++
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();
}
}
}
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center. –
Cashbook
© 2022 - 2024 — McMap. All rights reserved.