【问题标题】:Waiting for all USB drives to load等待所有 USB 驱动器加载
【发布时间】:2016-07-20 10:22:44
【问题描述】:

我目前正在使用具有分支逻辑的应用程序,具体取决于是否将特定 USB 驱动器插入系统。它通过轮询所有驱动器号来查找每个驱动器根目录上的路径来做到这一点。

这适用于大多数机器,但通常,该应用程序在插入 USB 驱动器的情况下在启动时运行。此外,有些机器速度特别慢,一旦 Windows 启动,加载 USB 驱动器需要很长时间。在这些机器中,代码到达检查这个驱动是否存在,找不到驱动,执行了错误的分支。

在检查驱动器之前可能需要等待一分钟。我宁愿让应用程序等待所有 USB 设备(或只是大容量存储设备)加载,然后再检查驱动器,或者更智能的东西。

不幸的是,我不熟悉等待所有 USB 设备完成加载所需的方法,以及一般的 DDK。我可以see 可以用GUID_DEVINTERFACE_USB_DEVICE 注册一个设备通知窗口,可能会收到DBT_DEVICEARRIVALDBT_DEVNODES_CHANGEDWM_DEVICECHANGE 之类的消息,我不知道它们的区别。

但是,在程序执行之前,USB 驱动器可能已经插入并被检测到(但没有驱动器号)到系统中。因此,注册所有设备更改通知是没有意义的。如果可以识别已插入但未加载的设备(可能使用SetupDiEnumDeviceInterfaces),然后在所有这些设备上注册“已加载”通知,它可能会起作用。我对此一无所知,因此指针(或示例代码)会非常有帮助。

【问题讨论】:

  • “我希望应用程序等待所有 USB 设备” - 这要求您为 “所有 USB 设备提供一个简明的规范" 包含。由于 USB 设备可以支持热插拔,因此很难指定。此外,您在 USB 驱动器和驱动器号之间的 1:1 映射存在缺陷。 USB 设备可以分配零个或多个驱动器号。并且为每个用户分配驱动器号。因此,在服务中处理驱动器号是毫无意义的。 (假设您正在编写服务,因为您谈论的是启动时初始化。)
  • @IInspectable:实际上,驱动器号是系统范围分配(本地磁盘)和每个会话分配(远程共享,使用用户凭据)的结合。 U盘是本地的。但是有一些小的魔法 IIRC 可以避免选择已经用于远程共享的字母。
  • @IInspectable 假设仅枚举“可移动”卷,无论它是否具有驱动器号。卷 GUID 仍然无法访问它们。这些驱动器还包含一个完整的 NTFS 分区。
  • 正如我所说,您需要一个简洁的规范。重复 "all" 并不能解释太多,因为随着时间的推移,热插拔使可用性成为一项功能。
  • 我要求 API 等效于检测通知区域中的“驱动器软件安装”当前是否显示任何当前正在加载的设备,并在当前列出的设备可用时收到通知使用(即出现驱动器号时),或者设备已断开连接。我不确定可以解释我需要什么的精确(简洁)定义。我想知道是否有 USB 大容量存储设备已连接但尚未完成加载,并在某个卷可用(或驱动器已断开连接)时收到通知。

标签: c winapi usb usb-drive


【解决方案1】:

我不认为你可以。

问题在于您正试图区分两种实际上并不明显的情况,即在启动期间插入 USB 设备并稍后再插入。

您必须知道 USB 是一种协议,它需要 USB 从设备中的大量智能。它们与 USB 主机(即您的操作系统)交换多条消息。这种交换不是即时的。例如,您的 USB 硬盘驱动器需要请求获得超过 100mA 电流的许可。要回答这个问题,Windows 的电源驱动程序必须启动并运行。只有当答案到来时,物理磁盘才能旋转起来。

所以,有一个完整的消息序列,驱动器号只是很晚才出现。 Windows 必须知道存在多少个分区。所以在这次交流中,新设备一直在被创造出来。

当您枚举设备时正在积极添加设备,您确实是在自找麻烦。 SetupDiEnumDeviceInterfaces API 不对快照进行操作(我们知道这是因为没有 Close 方法);您要求第 N 个设备,直到您收到“没有更多设备”错误并且您知道 N 太大了。但是当设备仍在积极添加时,N 会发生变化。而且我看不到列表顺序是按年龄排列的保证;也可以在中间添加设备。

【讨论】:

  • 我想我要求 API 等效于检测通知区域中的“驱动器软件安装”当前是否显示任何当前正在加载的设备,并在当前列出的设备时收到通知可以使用(即出现驱动器号时)。
【解决方案2】:

我认为收到有关为新插入的设备安装驱动程序的通知对您没有多大帮助。当您重复插入同一设备时,驱动程序通常只在第一次安装。

此外,USB 闪存驱动器虽然在物理上看起来像一个紧凑型设备,但在 Windows 中至少由三个 PnP 设备表示:一个 USB 大容量存储设备(代表 USB 端点)、一个磁盘设备(代表内部的物理磁盘闪存驱动器)和一个或多个卷设备(在您的情况下,每个代表一个卷 = 分区)。驱动器号可以分配给卷设备。

您可以做的是监控卷设备的到达和移除(GUID_DEVINTERFACE_VOLUME 的RegisterDeviceNotification)并检查每个到达的卷设备(我相信Setup API 允许您跟踪它的“父母”到USB 堆栈)。

【讨论】:

    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 1970-01-01
    相关资源
    最近更新 更多