11

我有一个 USB 设备,它在收到命令时使用不同的接口、VID、PID 和序列号进行枚举,并且我想在发生此更改后跟踪物理设备。我的想法是通过它的枢纽和港口位置来跟踪它。

Win32_PnPSignedDriver类有一个看起来很完美的“位置”字段(例如Port_#0001.Hub_#0010,但它只包含第一次加载驱动程序时设备的位置。将硬件插入不同的端口不会更新该字段。

但是,该信息在某处可用,因为通过设备管理器查看设备时,“详细信息”选项卡下有一个“位置信息”字段。可以通过WMI 查询或其他方法检索此信息吗?有没有更好的方法来解决这个问题?

编辑:我知道这听起来很奇怪。这些设备中的微控制器包含一个作为 CDC 设备(即串行端口)枚举并允许编程的 ROM。在制造过程中,跟踪设备是有益的,因为它在制造商的 ROM(唯一 VID/PID/序列号)和我的自定义固件接口(不同的 VID/PID/序列号)之间变化。

4

5 回答 5

10

我知道这个答案的任何活动已经有一段时间了,但我正在研究一个需要与此类似的功能的项目,我可以告诉你这确实是可能的。据我所知,它确实需要 DDK 并且PInvoke没有 C# 或 WMI 接口来获取此信息。它需要打开底层 USB 根集线器设备,并直接向它们发送驱动 IOCTL 命令。

好消息是,Microsoft 提供了一个示例 C++ 应用程序,它完全枚举所有 USB 设备并准确显示它们连接到哪些端口。该应用程序是USBView 示例应用程序

我想你会发现,如果你编译并运行这个应用程序,你会看到它准确地显示了你的设备插入的位置,如果你将任何设备插入该端口,它会显示在同一个地方。如果您创建一个非托管 C++ DLL 提供一些调用,您的 C# 应用程序可以使用这些调用来获取它所需的信息,也许会更容易。

EnumerateHubPorts()它对代码中的函数有这样的说法:

给定一个开放集线器的句柄和集线器上下游端口的数量,为集线器的每个下游端口发送一个 IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX 请求,以获取有关连接到每个端口的设备(如果有)的信息。

要了解这需要的所有内容(必须从顶部开始枚举所有内容,即使您只对一个端口感兴趣),以下是enum.c代码中文件顶部列出的注释:

/*

This source file contains the routines which enumerate the USB bus
and populate the TreeView control.

The enumeration process goes like this:

(1) Enumerate Host Controllers and Root Hubs
EnumerateHostControllers()
EnumerateHostController()
Host controllers currently have symbolic link names of the form HCDx,
where x starts at 0.  Use CreateFile() to open each host controller
symbolic link.  Create a node in the TreeView to represent each host
controller.

GetRootHubName()
After a host controller has been opened, send the host controller an
IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of
the root hub that is part of the host controller.

(2) Enumerate Hubs (Root Hubs and External Hubs)
EnumerateHub()
Given the name of a hub, use CreateFile() to map the hub.  Send the
hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the
hub, such as the number of downstream ports.  Create a node in the
TreeView to represent each hub.

(3) Enumerate Downstream Ports
EnumerateHubPorts()
Given an handle to an open hub and the number of downstream ports on
the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
request for each downstream port of the hub to get info about the
device (if any) attached to each port.  If there is a device attached
to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request
to get the symbolic link name of the hub attached to the downstream
port.  If there is a hub attached to the downstream port, recurse to
step (2).  

GetAllStringDescriptors()
GetConfigDescriptor()
Create a node in the TreeView to represent each hub port
and attached device.
*/
于 2013-02-09T07:10:19.337 回答
2

设备管理器下的“位置信息”与您通过 WMI 获得的字符串完全相同。

您是否考虑过,当设备插入不同的端口时,Windows 不会使用新位置更新元数据,而是创建新的驱动程序实例和新的元数据。尝试Win32_PnPDevice仅针对当前插入的对象实例过滤对象实例,我想您会找到当前位置信息。

例如,如果我将 USB 鼠标移动到不同的端口,则与旧端口关联的鼠标副本仍列在设备管理器下,默认情况下只是隐藏。有关查看这些断开连接的设备的说明,请参阅http://oreilly.com/pub/h/3105。或者从提升的管理员命令提示符运行以下命令:

C:\Windows\system32>set devmgr_show_nonpresent_devices=1
C:\Windows\system32>devmgmt
于 2011-07-01T16:48:48.240 回答
2

你试过SetupDi吗?您可以使用 API 函数的 SetupDi 类从 DeviceManager 中获取信息。

于 2011-07-01T16:39:00.833 回答
0

REF:“Win32_PnPSignedDriver 类有一个“位置”字段,看起来很完美(例如 Port_#0001.Hub_#0010),但它只包含第一次加载驱动程序时设备的位置。将硬件插入不同的端口确实不更新该字段。”

它对我有用。但是,请务必在端口交换之间刷新 (F5) regedit 应用程序,否则您将看不到更改。

这里有些例子:

端口 2 集线器
2 端口 2集线器 4 端口 3
集线器 4

于 2020-08-31T10:30:57.797 回答
-2

更好的想法是使用 USB 设备的唯一序列号。

于 2011-06-27T06:10:50.887 回答