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