2010-11-14 11 views
8

Estoy desarrollando un fragmento de código C que usa ReadDirectoryChangesW() para supervisar los cambios bajo un directorio en Windows. He leído las entradas de MSDN relacionadas para ReadDirectoryChangesW() y la estructura FILE_NOTIFY_INFORMATION, así como otras piezas de documentación. En este punto, he logrado monitorear múltiples directorios sin problemas aparentes en el monitoreo en sí. El problema es que los nombres de archivo puestos en la estructura FILE_NOTIFY_INFORMATION por esta función no son canónicos.¿Cómo lidiar con ReadDirectoryChangesW() de Windows y su salida mixta de nombre largo/corto?

Según MSDN pueden ser en forma larga o corta. He encontrado varias publicaciones que sugieren el almacenamiento en caché de rutas cortas y largas para manejar este caso. Desafortunadamente, según mis propias pruebas en un sistema con Windows 7, esto no es suficiente para eliminar el problema, porque no hay solo dos alternativas para cada nombre de archivo. El problema es que en un nombre de ruta CADA COMPONENTE puede estar en forma larga o corta. todas las siguientes rutas de acceso pueden hacer referencia al mismo archivo:

c: \ ~ 1 \ MYPROG ~ 1 \ MYDATA ~ 1.TXT

c: \ ~ 1 \ MYPROG ~ 1 \ MyDataFile.txt

c: \ ~ 1 \ MiPrograma \ MYDATA ~ 1.TXT

c: \ ~ 1 \ MiPrograma \ MyDataFile.txt

c: \ archivos de programa \ MYPROG ~ 1 \ ~ 1 MYDATA .TXT

...

y por lo que puedo decir de mis pruebas con cmd.exe son perfectamente aceptables. Básicamente, el número de rutas válidas para cada archivo se eleva exponentialy con el número de componentes en su nombre de ruta.

Desafortunadamente, ReadDirectoryChangesW() parece rellenar su búfer de salida con los nombres de archivo proporcionados a la llamada del sistema que causa cada operación. Por ejemplo, si usa los comandos cmd.exe para crear, cambiar el nombre, eliminar e.t.c. archivos, FILE_NOTIFY_INFORMATION contendrá los nombres de archivo como se especifica en la línea de comando.

Ahora, en la mayoría de los casos podría usar GetLongPathName() y mis amigos para obtener una ruta única para mi uso. Lamentablemente, eso no se puede hacer al eliminar archivos: cuando recibo la notificación, el archivo ya no está y las funciones Get * PathName() no funcionarán.

Por el momento estoy pensando en usar un caché más extenso para determinar qué rutas alternativas utilizan las aplicaciones para cada archivo, lo que manejaría cualquier caso, excepto el que decida eliminar un archivo de la nada con un nombre de ruta mixto no visto Y estoy pensando en la extracción de datos creativos a partir de los eventos de modificación del directorio padre y volviendo a consultar el directorio real para ese caso.

¿Alguna sugerencia para una manera más fácil de hacer esto?

PS1: Si bien las revistas de cambios se ocuparían de esto de manera efectiva (espero) no creo poder utilizarlas, debido a sus vínculos con NTFS y la falta de privilegios de administrador para mi aplicación. Prefiero no ir allí, a menos que esté absolutamente obligado a hacerlo.

PS2: Por favor, tenga en cuenta que codificaré principalmente en Unix, así que se gentil ...

+0

Si todo lo demás falla, ¿quizás funcionará un controlador de minifiltro? – wj32

+0

Creo que eso es lo que hacen la mayoría de los programas antivirus y supongo que sería LA solución para este problema. Desafortunadamente, requiere la instalación de derechos de administrador del sistema, y ​​al igual que en Change Journals, la arquitectura de mi aplicación sería mucho más compleja, ya que tendría que considerar cuestiones de seguridad y estabilidad con las que no tengo que lidiar ahora. Y no olvidemos las dificultades inherentes de escribir un controlador kernel-mode o cuasi-kernel-mode para cualquier sistema operativo. – thkala

+0

Ah, y por el momento parece un poco excesivo controlar todo solo para ver un par de directorios de usuarios. Gracias por la sugerencia, aunque ... – thkala

Respuesta

1

No es necesario almacenar en caché todas las combinaciones. Lo hará si almacena en caché cada subpaso para poder convertirlo a la forma larga.por ejemplo tienda esta:

  • C:\PROGRA~1 => c:\Program Files
  • c:\Program Files\MYPROG~1 => c:\Program Files\MyProgram
  • c:\Program Files\MyProgram\MYDATA~1.TXT => c:\Program Files\MyProgram\MyDataFile.txt
  • c:\Program Files\MyProgram\MYDATA~2.TXT => c:\Program Files\MyProgram\MyDataFile2.txt

Ahora bien, si se obtiene una notificación de c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT, dividirlo en cada \, y las operaciones de búsqueda cada parte de es una forma larga.

No olvide que MyDataFile.txt y MYDATAFILE.TXT también apuntan al mismo archivo. Así que compare las mayúsculas y minúsculas o conviértalo todo a mayúsculas.

Y si se elimina c:\PROGRA~1\MYPROG~1\MYDATA~1.TXT, igual puede usar GetLongPathName() en c:\PROGRA~1\MYPROG~1.

+0

Cuando mencioné el almacenamiento en caché y la minería de datos extensivo, tuve en mente una versión un poco más mejorada de lo que propones. En este momento estoy almacenando nombres cortos y largos cuando están disponibles y cuando se ha visto una ruta, ya puedo encontrar todos los nombres de ruta alternativos. Usando una asociación c: \ A \ B \ C -> c: \ a \ b \ c puedo detectar todas las combinaciones c: \ {A, \} \ {B, b} \ {C, c}. Todavía existe un problema con las eliminaciones de archivos no vistos. Estoy pensando en almacenar de manera recursiva un estado inicial del directorio para tratar con esto, no estoy seguro si puedo evitarlo de todos modos ... – thkala

Cuestiones relacionadas