2010-10-12 14 views
11

¿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:

  1. 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 el devInst 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 utilizando CM_Request_Device_Eject.

  2. usando DeviceIoControl con el código de control IOCTL_STORAGE_EJECT_MEDIA. La secuencia de eventos es:

    Esto no funciona en absoluto. Cada una de las llamadas DeviceIoControl falla con ERROR_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.

+0

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

+0

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

+0

@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. –

Respuesta

1

Eventualmente, descubrí que estaba cometiendo un error con el acercamiento # 2.

Resulta que por alguna razón no estaba configurando correctamente el acceso deseado al abrir el controlador del volumen usando CreateFile.

El modo de acceso correcto es GENERIC_READ | GENERIC_WRITE y estaba pasando 0. Después de corregir mi error, pude expulsar con éxito el dispositivo usando DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, así como con el método n. ° 1, utilizando CM_Request_Device_Eject.

Finalmente, resulta que el método n. ° 2 es de hecho el método utilizado por la función "Expulsar" del menú de contexto del intérprete de comandos. Al usar este método, el dispositivo reacciona correctamente.

0

Intente seguir How to Prepare a USB Drive for Safe Removal que muestra cómo utilizar la función CM_Request_Device_Eject.

+0

Gracias @Oleg, pero ese enfoque es exactamente lo que describí como la solución n. ° 1, que funciona porque expulsa el USB pero no hace lo mismo que Windows cuando hace clic en "Expulsar" en el menú contextual de Shell. Eso es lo que necesito ... –

+0

@Miky Dinescu: ¿por qué necesita saber exactamente qué hacen las ventanas en el menú contextual de Shell? Supongo que debe tener una forma que funcione y no necesite privilegios de administrador. El artículo del proyecto de código es lo suficientemente antiguo, puedes descargar el ejemplo de código completo que funciona. ¿Por qué necesita saber qué menú contextual de shell hacer? – Oleg

+0

Porque la expulsión del dispositivo del shell de Windows desencadena una acción en este dispositivo; para abreviar, simplemente digamos que un LED se enciende. Cuando expulso el dispositivo de mi aplicación utilizando el método CM_Request_Device_Eject, el dispositivo se expulsa, pero el LED no se enciende. Y sí, lo he comprobado, es lo mismo que la implementación del proyecto de código. Y estoy bastante familiarizado con lo que ya está disponible en los foros, incluido CodeProject, ya que he estado buscando en Internet durante dos días tratando de resolver esto. ¿Tiene alguna otra sugerencia? –

0

Vine aquí accidentalmente mientras hacía una búsqueda en "CM_Request_Device_Eject", y vi que era similar a una solución que había hecho recientemente juntando piezas similares de una solución. Perdona la respuesta tardía.

He resumido los pasos que he hecho para esto en mi proyecto in this SO answer.

+0

En realidad, he respondido mi propia pregunta a hace unos años (ver la edición en la pregunta). Gracias por sonar. –

Cuestiones relacionadas