2009-11-17 11 views
5

Estoy viendo un directorio llamando al ReadDirectoryChangesW sincrónicamente. Cuando hay un archivo nuevo disponible, intento acceder de inmediato con CreateFile con GENERIC_READ y FILE_SHARE_READ, pero esto me da ERROR_SHARING_VIOLATION. El proceso que coloca el archivo en el directorio supervisado no termina de escribirse cuando intento leerlo.Esperando hasta que haya un archivo disponible para leer con Win32

¿Hay alguna manera de esperar de manera confiable hasta que el archivo esté disponible para la lectura? Puedo poner el método en un ciclo como el siguiente, pero espero que haya una mejor manera.

while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) 
     Sleep (500); 
    else 
     break; // some other error occurred 
} 

if (hFile == INVALID_HANDLE_VALUE) 
{ 
    // deal with other error 
    return 0; 
} 

ReadFile (...); 
+0

Supongo que esto es C++? Si es C#, hay un objeto SystemFileWatcher en el BCL que puede usar. –

+0

Win32 == C API, voy a volver a etiquetar. – dreamlax

Respuesta

2

No hay API de modo de usuario para las notificaciones en un archivo cerrado del que soy consciente. El ciclo que ha propuesto es probablemente la mejor manera. La única otra cosa que podría hacer sería mirar por CloseFile en un controlador de filtro ala Process Monitor, pero yuck ...

0

Si sabe algo acerca de cómo se crea el archivo, quizás espere hasta que el archivo deje de crecer para X segundos o espere hasta que se elimine un archivo centinela. O siente el estado del programa que los crea.

+0

Lamentablemente no tengo ni idea de cómo se genera el archivo o el proceso que lo está colocando en la carpeta observada (podría ser cualquier programa, o podría ser el usuario arrastrando y soltando un archivo, etc.). – dreamlax

5

No creo que haya una notificación para el tipo de evento que está buscando, pero como una mejora, sugeriría retrasos progresivos. De esta forma obtendrá tiempos de respuesta rápidos para cosas como arrastrar/soltar y no encerrará la CPU con un bucle cerrado si el usuario mantiene el archivo abierto durante una hora en Excel.

int delay= 10; 
while ((hFile = CreateFile (path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) 
{ 
    if (GetLastError() == ERROR_SHARING_VIOLATION) { 
     Sleep (delay); 
     if (delay<5120) // max delay approx 5.Sec 
      delay*= 2; 
    } 
    else 
     break; // some other error occurred 
} 
2

Como dijo @ Matt Davis, desafortunadamente no hay API en modo de usuario, pero hay una solución que dependiendo de su caso de uso (He escrito mina de abajo) pueden hacer precisamente lo que quiere.

lo que funcionó para mí en el pasado registraba para FILE_NOTIFY_CHANGE_LAST_WRITEen lugar deFILE_NOTIFY_CHANGE_FILE_NAME al llamar ReadDirectoryChangesW:

ZeroMemory(&overlapped, sizeof(OVERLAPPED)); 
overlapped.hEvent = hChangeEvent; 

// ...  
ReadDirectoryChangesW(hSpoolPath, 
         eventBuffer, 
         EVENT_BUF_LENGTH, 
         FALSE, 
         FILE_NOTIFY_CHANGE_LAST_WRITE, // <---- 
         NULL, 
         &overlapped, 
         NULL); 
// ... 
HANDLE events[2]; 

events[0] = hChangeEvent; 
events[1] = hCancelEvent; 

DWORD wRc = WaitForMultipleObjects(2, events, FALSE, DIRECTORY_WATCH_TIMEOUT); 

El último tiempo de escritura se actualiza tan pronto como el proceso propietario cierra el mango después de crear el archivo y escribiéndole

Mi caso de uso fue un proceso que recibió solicitudes HTTP a través de TCP/IP y escribió el cuerpo HTTP en un directorio, donde otro proceso lo recogió tan pronto como el proceso de recepción terminó (y cerró manejarlo). El servidor http fue el único proceso que se escribió en ese directorio, por lo que pude confiar en el patrón crear-escribir-cerrar.

+0

ReadDirectoryChangesW me notifica dos veces cuando me registro para FILE_NOTIFY_CHANGE_LAST_WRITE y luego agregue un archivo a la carpeta. ¿Qué notificación usaste? – Will

Cuestiones relacionadas