Notificación de cambios en un directorio

Os escribo de nuevo para ver si me podeis orientar sobre un pequeño tema que estoy realizando en Delphi 3.0 para Win’95. Lo que pretendo es comprobar si en un directorio de la red han copiado un fichero. Mi idea ha sido a través de un TTimer e ir comprobando el contenido del directorio, pero esto depende de la sobrecarga del equipo y de la multitarea. Me gustaría que me orientarais sobre algún otro método más eficaz.

La API de Windows dispone de una serie de funciones que nos permiten solicitar una notificación cada vez que se efectúe un cambio en un directorio o en los archivos que éste contiene. El método consiste en solicitar la notificación, mediante la función FindFirstChangeNotification, y quedar a la espera de que ésta se produzca, usando para ello la función WaitForSingleObject u otra de la misma familia. Puesto que esta última función detendría la ejecución del programa si la utilizamos en el hilo de ejecución principal, lo habitual es que el proceso de espera se efectúe en un hilo (thread) independiente. Esto no supone ningún problema en Delphi, basta con seleccionar la opción Thread Object del Depósito de objetos.
Partiendo de un nuevo proyecto Delphi seleccione la opción citada para añadir un nuevo módulo con una clase derivada de TThread, a la que vamos a llamar TActualiza. En el método Execute de esta clase será donde solicitemos la notificación por primera vez, usando para ello la citada función FindFirstChangeNotification. Esta llamada nos devuelve un identificador que guardaremos en una variable local. Seguidamente entramos en un bucle que se estará ejecutando indefinidamente. En su interior quedamos a la espera de que se produzca una notificación, usando para ello la función WaitForSingleObject. Al pasar INFINITE como segundo valor este hilo de ejecución quedará dormido sin límite de tiempo, hasta que en el directorio indicado en la llamada a FindFirstChangeNotification se produzca algún cambio. En este momento llamamos de forma sincronizada a la función ActualizaLista, con el fin de poder acceder en ella a un control TFileListBox que estará mostrando el contenido del directorio que se está controlando. Por último, mediante una llamada a FindNextChangeNotification, se solicita una nueva notificación cuando se produzca otro cambio, repitiéndose el proceso.

// Este método es el mundo de ejecución del nuevo hilo
procedure TActualiza.Execute;
Var
   Id: LongInt; // Identificador de la notificación
begin
       // Solicitamos una notificación de cambios de archivo en
       // la unidad C:
     Id := FindFirstChangeNotification('C:\', True,
                  FILE_NOTIFY_CHANGE_FILE_NAME);

     While True Do // Ejecutar siempre
      Begin
                // Esperamos que se produzca una modificación
           WaitForSingleObject(Id,INFINITE);
               // Actualizamos la lista
           Synchronize(ActualizaLista);
               // y esperamos la siguiente notificación
           FindNextChangeNotification(Id);
      End;
end;

En el formulario de este programa de prueba habrá que insertar el código necesario para crear un objeto TActualiza. El lugar apropiado para ello es el método asociado al evento OnCreate de la ventana. La creación la efectuaremos con la siguiente sentencia:

ActualizaVista := TActualiza.Create(False);

Observe que se pasa como parámetro al constructor el valor False, indicando que el nuevo hilo de ejecución no ha de iniciarse en estado de espera, sino directamente en estado de ejecución.
En el archivo de código podrá encontrar el proyecto NotificacionCambios.DPR con el código de este programa. En este caso se ha insertado en el código del objeto TActualiza el camino que se quiere inspeccionar, pero en la práctica se podría añadir un constructor que permitiese especificar ese parámetro. De esta forma sería posible crear varios objetos TActualiza simultáneamente, cada uno funcionando en un hilo de ejecución separado e inspeccionando los cambios de un directorio diferente.