C# 获取父设备

C# 获取父设备,c#,windows,device-instance-id,C#,Windows,Device Instance Id,我有两个USB设备ID,例如USB\VID_E4F1和PID_0661\00000 115fa9ce7750000000000000000和USB\VID_E4F1和PID_0661&MI_00\7&B5A5DDF&0&0000 如何验证设备#2是设备#1的直接子设备(实际上它们是同一USB复合设备的不同部分) 在现实生活中,它们中的许多连接到同一个USB控制器。此外,它们可能是同一制造商和型号的。这就是为什么我无法验证VID、PID,并使用Win32_USBControllerDeviceWM

我有两个USB设备ID,例如
USB\VID_E4F1和PID_0661\00000 115fa9ce7750000000000000000
USB\VID_E4F1和PID_0661&MI_00\7&B5A5DDF&0&0000

如何验证设备#2是设备#1的直接子设备(实际上它们是同一USB复合设备的不同部分)

在现实生活中,它们中的许多连接到同一个USB控制器。此外,它们可能是同一制造商和型号的。这就是为什么我无法验证VID、PID,并使用Win32_USBControllerDeviceWMI查询来验证它们是否插入同一个USB控制器-我需要以某种方式验证父子关系,而不仅仅是验证它们是否插入同一个控制器

如果有必要,我只需要支持Windows 8+。

这里是您的朋友:

  • 打开给定设备ID的设备句柄

  • 查找父设备

  • 并获取设备句柄并返回设备ID


如果您能够使用新的WinRT API,您应该查看
PnpObject
类和命名空间

下面是一个代码示例:

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")
        }
    }
}
var propertiesToQuery=new List(){
“System.ItemNameDisplay”,
“System.Devices.DeviceInstanceId”,
“System.Devices.Parent”,
“系统.设备.位置路径”,
“系统.设备.子对象”
};
变量id1=@“USB\VID_E4F1和PID_0661\00000 115FA9CE7750000000000000000”;
var device1=等待PnpObject.findalsync(PnpObjectType.Device,
属性查询,
“System.Devices.DeviceInstanceId:=\”“+id1+”\”;
变量id2=@“USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000”;
var device2=等待PnpObject.findalsync(PnpObjectType.Device,
属性查询,
“System.Devices.DeviceInstanceId:=\”“+id2+”\”;
var parent1=device1.Properties[“System.Devices.Parent”]作为字符串;
var parent2=device2.Properties[“System.Devices.Parent”]作为字符串;
if(parent1&&parent1==id2)
{
WriteLine(“设备2是设备1的父级”);
}
if(parent2&&parent2==id1)
{
WriteLine(“设备11是设备2的父设备”);
}
var child_id=device1.Properties[“System.Devices.Children”]作为字符串[];
if(子\u id!=null){
foreach(子对象id中的变量id)
{
if(id==id2){
WriteLine(“设备2是设备1的子设备”)
}
}
}
child_id=device2.Properties[“System.Devices.Children”]作为字符串[];
if(子\u id!=null){
foreach(子对象id中的变量id)
{
if(id==id1){
WriteLine(“设备1是设备2的子设备”)
}
}
}
如果这还不够,您可以尝试沿着父/子路径上下移动


您还可以查看
System.Devices.locationpath属性(一个字符串数组),并测试其中一个是否是另一个的前缀。

扩展Harry Johnston的伟大答案:

调用
CM\u Locate\u DevNode
后,可以通过单个函数调用获取父设备实例ID:

#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!
}
#包括
//获取父设备属性
DEVPROPTYPE-propType;
wchar_t propBuf[MAX_DEVICE_ID_LEN]={};
ULONG propBufSize=sizeof(propBuf);
CONFIGRET cres=CM_Get_DevNode_属性(devInst,(DEVPROPKEY*)和PKEY_Devices_Parent,&propType,(BYTE*)propBuf,&propBufSize,0);
如果(CRS==CR\U成功){
//propBuf现在包含父系统设备ID!
}

我不是专家,但我认为CM\u Locate\u DevNode、CM\u Get\u Parent和CM\u Get\u Device\u ID应该起作用。@HarryJohnston您已经忘记了CM\u Get\u Device\u ID\u的大小,但非常感谢,它很有魅力!您可能应该将您的评论复制粘贴到答案。您标记了问题C,但您接受了使用WINAPI的答案。。。c#标记不应该被移除吗?@gog据我记忆所及,我当时正在工作的项目是100%c#。它可以很好地使用WinAPI,请参见。