Как извлечь USB-съемный диск/том, аналогичный функции "Извлечь" в проводнике Windows?
Знаете ли вы, что такое API, или последовательность вызовов API, которые использует Windows для выполнения функции "Извлечь" , которая доступна в контекстном меню оболочки для съемных томов?
До сих пор я пробовал две вещи:
-
используя CM_Request_Device_Eject, я перечисляю съемные диски (используя API SetupDiXXX), найдите тот, который мне интересен, идите по иерархии диспетчера устройств (используя API CM_XXX) и, наконец, вызовите CM_Request_Device_Eject
на devInst
устройства, в которое я вовлечен. Это работает в том смысле, что он удаляет тома с "Мой компьютер" и делает устройство "безопасным для удаления" (готово к удалению), но оно не то же самое, что и контекстное меню оболочки "Извлечь" . То, как я это знаю, связано с тем, что устройство, которое я пытаюсь извлечь, должно делать что-то, когда оно выбрасывается, и что что-то не происходит, когда я делаю извлечения с помощью CM_Request_Device_Eject
.
-
используя DeviceIoControl с помощью 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 действительно является методом, используемым в контекстном меню оболочки "Извлечь" . Используя этот метод, устройство реагирует правильно.
Ответы
Ответ 1
В конце концов, я узнал, где я ошибся с подходом № 2.
Оказывается, по какой-то причине я неправильно установил нужный доступ при открытии дескриптора тома с помощью CreateFile.
Правильный режим доступа GENERIC_READ | GENERIC_WRITE
, и я прошел 0
. После исправления моей ошибки я смог успешно извлечь устройство с помощью DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, а также с помощью метода # 1, используя CM_Request_Device_Eject.
Наконец, оказывается, что метод # 2 действительно является методом, используемым контекстным меню оболочки "Извлечь". Используя этот метод, устройство реагирует правильно.
Ответ 2
Попробуйте следовать Как подготовить USB-накопитель для безопасного удаления, в котором показано, как использовать CM_Request_Device_Eject.
Ответ 3
Я случайно пришел сюда, выполняя поиск в "CM_Request_Device_Eject", и увидел, что он был похож на решение, которое я недавно сделал, объединив аналогичные части решения. Простите поздний ответ.
Я кратко изложил шаги, которые я сделал для этого в моем проекте в этом SO-ответе.