我只知道USB驱动器的供应商和产品ID,但我需要能够获取与此设备关联的所有驱动器号。
System.IO.DriveInfo没有提供可以找到vid / pid的任何ID。
LibUsb包装器存在相反的问题-大量的id信息,但是我无法连接到安装点。
答案 0 :(得分:1)
这是一个对我有用的解决方案,为您提供与您的供应商和产品ID匹配的所有驱动器。并不是所有的代码都是我写的。
#include <windows.h>
#include <stdio.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <winioctl.h>
#define BUFFER_SIZE 256
#define MAX_DRIVES 26
// Finds the device interface for the CDROM drive with the given interface number.
DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber)
{
const GUID *guid = &GUID_DEVINTERFACE_DISK;
// Get device interface info set handle
// for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
return 0;
// Retrieve a context structure for a device interface of a device information set.
BYTE buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
// Iterate through all the interfaces and try to match one based on
// the device number.
for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, i, &spdid); i++)
{
// Get the device path.
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL);
if (dwSize == 0 || dwSize > sizeof(buf))
continue;
pspdidd->cbSize = sizeof(*pspdidd);
ZeroMemory((PVOID)&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd,
dwSize, &dwSize, &spdd))
continue;
// Open the device.
HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDrive == INVALID_HANDLE_VALUE)
continue;
// Get the device number.
STORAGE_DEVICE_NUMBER sdn;
dwSize = 0;
if (DeviceIoControl(hDrive,
IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &sdn, sizeof(sdn),
&dwSize, NULL))
{
// Does it match?
if (DeviceNumber == (long)sdn.DeviceNumber)
{
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
// Returns true if the given device instance belongs to the USB device with the given VID and PID.
boolean matchDevInstToUsbDevice(DEVINST device, DWORD vid, DWORD pid)
{
// This is the string we will be searching for in the device harware IDs.
TCHAR hwid[64];
sprintf(hwid, "VID_%04X&PID_%04X", vid, pid);
// Get a list of hardware IDs for all USB devices.
ULONG ulLen;
CM_Get_Device_ID_List_Size(&ulLen, NULL, CM_GETIDLIST_FILTER_NONE);
TCHAR *pszBuffer = malloc(sizeof(TCHAR) * ulLen);
CM_Get_Device_ID_List(NULL, pszBuffer, ulLen, CM_GETIDLIST_FILTER_NONE);
// Iterate through the list looking for our ID.
for (LPTSTR pszDeviceID = pszBuffer; *pszDeviceID; pszDeviceID += _tcslen(pszDeviceID) + 1)
{
// Some versions of Windows have the string in upper case and other versions have it
// in lower case so just make it all upper.
for (int i = 0; pszDeviceID[i]; i++)
pszDeviceID[i] = toupper(pszDeviceID[i]);
if (_tcsstr(pszDeviceID, hwid))
{
// Found the device, now we want the grandchild device, which is the "generic volume"
DEVINST MSDInst = 0;
if (CR_SUCCESS == CM_Locate_DevNode(&MSDInst, pszDeviceID, CM_LOCATE_DEVNODE_NORMAL))
{
DEVINST DiskDriveInst = 0;
if (CR_SUCCESS == CM_Get_Child(&DiskDriveInst, MSDInst, 0))
{
// Now compare the grandchild node against the given device instance.
if (device == DiskDriveInst)
return TRUE;
}
}
}
}
return FALSE;
}
int scan_drives(DWORD vid, DWORD pid)
{
TCHAR caDrive[4] = TEXT("A:\\");
TCHAR volume[BUFFER_SIZE];
TCHAR volume_path_name[BUFFER_SIZE];
DWORD dwDriveMask;
int count = 0;
// Get all drives in the system.
dwDriveMask = GetLogicalDrives();
if (dwDriveMask == 0)
{
printf("Error - GetLogicalDrives failed\n");
return -1;
}
// Loop for all drives.
for (int nLoopIndex = 0; nLoopIndex < MAX_DRIVES; nLoopIndex++, dwDriveMask >>= 1)
{
// If a drive is present,
if (dwDriveMask & 1)
{
caDrive[0] = TEXT('A') + nLoopIndex;
// If a drive is removable.
if (GetDriveType(caDrive) == DRIVE_REMOVABLE)
{
//Get its volume info.
if (GetVolumeNameForVolumeMountPoint(caDrive, volume, BUFFER_SIZE))
{
DWORD lpcchReturnLength;
GetVolumePathNamesForVolumeName(volume, volume_path_name, BUFFER_SIZE, &lpcchReturnLength);
char szVolumeAccessPath[] = "\\\\.\\X:";
szVolumeAccessPath[4] = caDrive[0];
long DeviceNumber = -1;
HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hVolume == INVALID_HANDLE_VALUE)
{
return 1;
}
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if (res)
{
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if (DeviceNumber != -1)
{
DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber);
boolean match = matchDevInstToUsbDevice(DevInst, vid, pid);
if (match)
{
printf("%s\t0x%04x\t0x%04x\n", volume_path_name, vid, pid);
}
}
count++;
}
}
}
}
return count;
}
int main(int argc, char *argv[])
{
if (argc > 1)
{
if (argc % 2 == 0)
{
return -1;
}
for (int i = 1; i < argc - 1; i += 2)
{
int vid, pid;
sscanf(argv[i], "%x", &vid);
sscanf(argv[i + 1], "%x", &pid);
scan_drives(vid, pid);
}
}
return 0;
}
答案 1 :(得分:0)
几年前有一个related post。
我修改了答案的代码:
static void Main(string[] args)
{
// example call
string device = FindPath("VID_0781&PID_5583");
GetDriveLetter(device);
}
static public string FindPath(string pattern)
{
var USBobjects = new List<string>();
string Entity = "*none*";
foreach (ManagementObject entity in new ManagementObjectSearcher(
$"select * from Win32_USBHub Where DeviceID Like '%{pattern}%'").Get())
{
Entity = entity["DeviceID"].ToString();
foreach (ManagementObject controller in entity.GetRelated("Win32_USBController"))
{
foreach (ManagementObject obj in new ManagementObjectSearcher(
"ASSOCIATORS OF {Win32_USBController.DeviceID='"
+ controller["PNPDeviceID"].ToString() + "'}").Get())
{
if (obj.ToString().Contains("DeviceID"))
USBobjects.Add(obj["DeviceID"].ToString());
}
}
}
int VidPidposition = USBobjects.IndexOf(Entity);
for (int i = VidPidposition; i <= USBobjects.Count; i++)
{
if (USBobjects[i].Contains("USBSTOR"))
{
return USBobjects[i];
}
}
return "*none*";
}
public static void GetDriveLetter(string device)
{
int driveCount = 0;
foreach (ManagementObject drive in new ManagementObjectSearcher("select * from Win32_DiskDrive").Get())
{
if (drive["PNPDeviceID"].ToString() == device)
{
foreach (ManagementObject o in drive.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject i in o.GetRelated("Win32_LogicalDisk"))
{
Console.WriteLine("Disk: " + i["Name"].ToString());
driveCount++;
}
}
}
}
if (driveCount == 0)
{
Console.WriteLine("No drive identified!");
}
}
一些错误处理和优化很有意义。