【问题标题】:Get parent device获取父设备
【发布时间】:2014-09-24 04:45:57
【问题描述】:

我有两个 USB 设备 ID,例如USB\VID_E4F1&PID_0661\00000115FA9CE7750000000000000000USB\VID_E4F1&PID_0661&MI_00\7&B5A5DDF&0&0000

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

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

如果重要的话,我只需要支持 Windows 8+。

【问题讨论】:

  • 我不是专家,但我认为 CM_Locate_DevNode、CM_Get_Parent 和 CM_Get_Device_ID 应该可以解决问题。
  • @HarryJohnston 你忘记了 CM_Get_Device_ID_Size,但非常感谢,它就像一个魅力!您可能应该将您的评论复制粘贴到答案中。
  • 您标记了问题 C#,但您接受了使用 WINAPI 的答案...不应该删除 c# 标记吗?
  • @gog 据我记得,我当时从事的项目是 100% C#。它可以很好地使用 WinAPI,参见例如pinvoke.net/default.aspx/setupapi/CM_Locate_DevNodeA%20.html

标签: c# windows device-instance-id


【解决方案1】:

PnP Configuration Manager API 是你的朋友:

【讨论】:

    【解决方案2】:

    如果您能够使用新的 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")
            }
        }
    }
    

    如果这还不够,您可以尝试向上或向下父/子路径。

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

    【讨论】:

      【解决方案3】:

      扩展 Harry Johnston 的精彩回答:

      调用CM_Locate_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!
      }
      

      【讨论】:

        猜你喜欢
        • 2017-03-11
        • 1970-01-01
        • 2010-10-15
        • 1970-01-01
        • 1970-01-01
        • 2014-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多