问题
I have two USB device IDs, e.g. USB\VID_E4F1&PID_0661\00000115FA9CE7750000000000000000
and USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000
How to verify device #2 is a direct child of device #1 (physically they’re different parts of the same USB composite device)?
In real-life scenarios it will be many of them connected to the same USB controller. Moreover, it's possible they'll be of the same maker and model. That's why I cant verify the VID, PID, and use Win32_USBControllerDevice
WMI query to verify they're plugged into the same USB controller - I need to somehow verify the parent-child relation, not just the fact they're plugged into the same controller.
If it matters, I only need to support Windows 8+.
回答1:
The PnP Configuration Manager API is your friend here:
CM_Locate_DevNode opens a device handle given a device ID;
CM_Get_Parent finds the parent device;
CM_Get_Device_ID_Size and CM_Get_Device_ID take the device handle and return the device ID.
回答2:
If you are able to use the new WinRT API You should take a look at the PnpObject
class and namespace.
Here's a code example:
var propertiesToQuery = new List<string>() {
"System.ItemNameDisplay",
"System.Devices.DeviceInstanceId",
"System.Devices.Parent",
"System.Devices.LocationPaths",
"System.Devices.Children"
};
var id1 = @"USB\VID_E4F1&PID_0661\00000115FA9CE7750000000000000000";
var device1 = await PnpObject.FindAllAsync(PnpObjectType.Device,
propertiesToQuery,
"System.Devices.DeviceInstanceId:=\"" + id1 + "\"");
var id2 = @"USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000";
var device2 = await PnpObject.FindAllAsync(PnpObjectType.Device,
propertiesToQuery,
"System.Devices.DeviceInstanceId:=\"" + id2 + "\"");
var parent1 = device1.Properties["System.Devices.Parent"] as string;
var parent2 = device2.Properties["System.Devices.Parent"] as string;
if (parent1 && parent1 == id2)
{
WriteLine("Device 2 is parent of device 1");
}
if (parent2 && parent2 == id1)
{
WriteLine("Device 11 is parent of device 2");
}
var child_ids = device1.Properties["System.Devices.Children"] as string[];
if (child_ids != null){
foreach (var id in child_ids)
{
if (id == id2){
WriteLine("Device 2 is child of device 1")
}
}
}
child_ids = device2.Properties["System.Devices.Children"] as string[];
if (child_ids != null){
foreach (var id in child_ids)
{
if (id == id1){
WriteLine("Device 1 is child of device 2")
}
}
}
If this is not enough you can try going up or down the parent/children path.
You could also look at the System.Devices.LocationPaths
property (which is an array of strings) and test if one is a prefix of the other.
回答3:
Extending the great answer by Harry Johnston:
Once you call CM_Locate_DevNode
, you can get the parent Device Instance ID with a single function call:
#include <propkey.h>
// Get the Parent Device Property
DEVPROPTYPE propType;
wchar_t propBuf[MAX_DEVICE_ID_LEN] = {};
ULONG propBufSize = sizeof(propBuf);
CONFIGRET cres = CM_Get_DevNode_Property(devInst, (DEVPROPKEY*)&PKEY_Devices_Parent, &propType, (BYTE*)propBuf, &propBufSize, 0);
if (cres == CR_SUCCESS) {
// propBuf now contains the Parent System Device ID!
}
来源:https://stackoverflow.com/questions/26008751/get-parent-device