【发布时间】:2019-05-30 11:47:18
【问题描述】:
您知道 Windows 使用什么 API 或 API 调用序列来完成可移动卷的外壳上下文菜单中可用的“弹出”功能吗?
到目前为止,我已经尝试了两件事:
使用CM_Request_Device_Eject,枚举可移动磁盘(使用SetupDiXXX APIs),找到我感兴趣的磁盘,遍历设备管理器层次结构(使用CM_XXX APIs),最后调用@987654335 @ 在我感兴趣的设备的
devInst上。这有效,因为它确实从我的电脑中删除了卷并使设备“安全删除”(准备删除) 但它与 shell 上下文菜单中的“弹出”功能不同。我知道这是因为我尝试弹出的设备应该在弹出时执行某些操作,而当我使用CM_Request_Device_Eject执行弹出时,something 不会发生。 p>-
将DeviceIoControl 与IOCTL_STORAGE_EJECT_MEDIA 控制代码一起使用。事件顺序是:
- 按照文档中的建议使用CreateFile 获取我感兴趣的卷的句柄
- 尝试使用FSCTL_LOCK_VOLUME 锁定卷
- 尝试使用FSCTL_DISMOUNT_VOLUME 卸载它
- 使用IOCTL_STORAGE_MEDIA_REMOVAL禁用防止存储媒体删除
- 最后执行IOCTL_STORAGE_EJECT_MEDIA函数。
这根本不起作用。每个
DeviceIoControl调用都以ERROR_IVALID_FUNCTION(0x00000001) 失败。我不知道为什么通话失败。我已经验证了对 DeviceIoControl 的其他调用对于同一个文件句柄(例如 IOCTL_STORAGE_GET_DEVICE_NUMBER)都可以正常工作
最后,我的开发机器运行的是 Windows 7 x64,为了让第二种方法正常工作,我尝试使用管理员权限运行我的应用程序,但这并没有改变任何东西。
编辑
最终,我发现了方法 #2 的错误之处。事实证明,由于某种原因,在使用CreateFile 打开卷的句柄时,我没有正确设置所需的访问权限。正确的访问模式是GENERIC_READ | GENERIC_WRITE,我通过了 0。更正错误后,我能够使用DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA 以及方法#1 成功弹出设备,使用CM_Request_Device_Eject。
事实证明,方法#2 确实是 shell 上下文菜单的“弹出”功能使用的方法。使用这种方法,设备反应正确。
【问题讨论】:
-
您的方法 #2 应该有效。在stackoverflow.com/questions/58670/windows-cdrom-eject 上,Andreas Magnusson 的回答对我有用,弹出了 U 盘。唯一的变化是更正了他的
DeviceIoControl的拼写。 -
另外,
DeviceIoControl成功返回1。当您报告收到ERROR_INVALID_FUNCTION时,是DeviceIoControl的返回值,还是返回0并且您正在调用GetLastError? -
感谢@Oleg,但这种方法正是我所描述的解决方案#1,它的工作原理是弹出 USB,但当您单击外壳上下文菜单。这就是我需要的..
-
@Nate:当我使用我提到的任一控制代码调用 DeviceIoControl 时,它确实返回 0。然后,当我调用 GetLastError() 时,它返回 1,即 ERROR_INVALID_FUNCTION。
标签: winapi usb removable-storage