¿Sabes cuál es la API o la secuencia de llamadas a la API que usa Windows para realizar la función "Expulsar" que está disponible en el menú contextual del shell para volúmenes extraíbles?Cómo expulsar un disco/volumen extraíble USB, similar a la función "Expulsar" en Windows Explorer?
Hasta ahora he intentado dos cosas:
utilizando CM_Request_Device_Eject, que enumeran los discos extraíbles (utilizando el SetupDiXXX APIs), encontrar el que más me interesa, caminar por la jerarquía de administrador de dispositivos (usando CM_XXX APIs) y finalmente llame al
CM_Request_Device_Eject
en eldevInst
del dispositivo en el que estoy interesado. Este funciona en el sentido de que elimina los volúmenes de Mi PC y hace que el dispositivo sea "seguro de quitar" (listo para ser eliminado) pero no es lo mismo que la función "Expulsar" del menú contextual del shell. La forma en que sé esto es porque se supone que el dispositivo que estoy intentando expulsar hace algo cuando se expulsa y que algo no está sucediendo cuando expulso utilizandoCM_Request_Device_Eject
.usando DeviceIoControl con el código de control IOCTL_STORAGE_EJECT_MEDIA. La secuencia de eventos es:
- obtener un identificador para el volumen estoy interesado en utilizar CreateFile como se sugiere en la documentación
- tratar de bloquear el volumen con FSCTL_LOCK_VOLUME
- intento de desmontar utilizando FSCTL_DISMOUNT_VOLUME
- deshabilitar la eliminación de medios de almacenamiento de prevención utilizando IOCTL_STORAGE_MEDIA_REMOVAL
- y finalmente ejecutar la función IOCTL_STORAGE_EJECT_MEDIA.
Esto no funciona en absoluto. Cada una de las llamadas
DeviceIoControl
falla conERROR_IVALID_FUNCTION
(0x00000001). No sé por qué las llamadas fallan. He verificado que otras llamadas a DeviceIOControl funcionan bien para el mismo identificador de archivo (como IOCTL_STORAGE_GET_DEVICE_NUMBER)
Por último, mi máquina de desarrollo se está ejecutando 7 x64 de Windows, y con el fin de obtener el segundo método de trabajar me Intenté ejecutar mi aplicación con privilegios de administrador y eso no cambió nada.
EDITAR
Finalmente, descubrí dónde estaba cometiendo un error con el enfoque # 2. Resulta que, por alguna razón, no estaba configurando correctamente el acceso deseado al abrir el controlador del volumen con CreateFile
. El modo de acceso correcto es GENERIC_READ | GENERIC_WRITE
y yo estaba pasando 0. Después de corregir mi error, pude expulsar el dispositivo con éxito utilizando DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA
, así como con el método n.º 1, usando CM_Request_Device_Eject
.
Y resulta que el método n. ° 2 es de hecho el método utilizado por la función "Expulsar" del menú contextual del intérprete de comandos. Al usar este método, el dispositivo reacciona correctamente.
Su enfoque # 2 debería funcionar. En http://stackoverflow.com/questions/58670/windows-cdrom-eject, la respuesta de Andreas Magnusson funcionó para mí, expulsando una memoria USB. El único cambio fue corregir su ortografía de 'DeviceIoControl'. – Nate
Además, 'DeviceIoControl' devuelve' 1' en caso de éxito. Cuando informa que obtiene 'ERROR_INVALID_FUNCTION', ¿es ese el valor de retorno de' DeviceIoControl', o está retornando '0' y está llamando' GetLastError'? – Nate
@Nate: DeviceIoControl devuelve 0 cuando lo llamo con cualquiera de los códigos de control que mencioné. Luego, cuando llamo a GetLastError(), devuelve 1 que es ERROR_INVALID_FUNCTION. –