Hacía ya bastante tiempo que no programaba por placer, principalmente por la falta de eso mismo, de tiempo libre.
Pero hace poco, revisando lo que tenían por el disco duro, me encontré con una aplicación que había desarrollado hacía bastante y decidí que era un buen momento para retomar su desarrollo.
Esta aplicación está hecha en mi querido Delphi (¡lo que he aprendido yo gracias a él!) para plataformas Windows (creo que vale cualquiera aunque lo he probado en Windows XP) y lo que muestra son todos los cambios que se producen en los archivos de nuestro sistema de archivos indicando si lo que ha cambiado es un archivo o un directorio, el tipo de cambio (adición, modificación, borrado o renombrado) y la ruta donde se ha producido el cambio.
Pero en realidad esta aplicación patata es el test que sirve para desarrollar una clase de Delphi que monitoriza los cambios que se producen en la ruta indicada de nuestro sistema de archivos: TFileSystemWatcher.
Como Delphi es un lenguaje de programación dirigida por eventos, cada vez que se produce un cambio en nuestros archivos o directorios, nuestra maravillosa clase, una vez arrancada, generará dos eventos: uno muy genérico dando información de qué ha pasado y otro más específico para poder realizar acciones propias de los cambios que queremos monitorizar.
Si se quiere ver como es por dentro la clase y los eventos que genera, se puede echar un vistazo a continuación:
{**
* @author Diego Lago <beosman@gmail.com>
* @version 0.1 20080318
* @license Creative Commons 2.5 – Reconocimiento – Compartir Igual
*
* @class TFileSystemWatcher
*
* Esta clase hereda de TThread y sirve para monitorizar los cambios en el sistema de
* archivos dada una ruta.
*
* Se pueden instanciar cuantas veces se quiera para monitorizar cualquier directorio.
* Los cambios que se pueden monitorizar son adiciones, borrados, modificaciones y
* renombraciones de archivos y directorios.
*
* Para cada acción se genera un evento genérico que siempre que hay una acción se activa,
* pero también hay eventos más específicos que se activan según el tipo de acción que
* ha ocurrido y según el tipo de archivo (si es archivo o directorio).
*
*}
type
{**
* Tipo de entrada, archivo o directorio, para el evento principal.
*}
TEntryType = (etDirectory,etFile);
{**
* Tipo de acción que se produce sobre el sistema de archivos.
*}
TFileSystemAction = (fsaNoAction,
fsaFileAdded,
fsaFileRemoved,
fsaFileModified,
fsaFileRenamedOldName,
fsaFileRenamedNewName);
{**
* Tipos de eventos producidos por esta clase.
*
* TFileSystemaChangeEvent: Evento genérico. Se produce siempre que hay un cambio en
* el sistema de archivos.
* TFileChangeEvent: Tipo de evento más específico. Se produce cuando hay un cambio en
* archivos o directorios de añadir, borrar y modificar.
* TFileRenamedEvent: Tipo de evento que se produce cuando se renombra un archivo o un
* directorio.
*
* Para más información ver los eventos declarados en la clase.
*}
TFileSystemChangeEvent = procedure(Sender: TObject; EntryType: TEntryType; Path: string; Action: TFileSystemAction) of object;
TFileChangeEvent = procedure(Sender: TObject; FilePath: string) of object;
TFileRenamedEvent = procedure(Sender: TObject; FileOldPath: string; FileNewPath: string) of object;
TFileSystemWatcher = class(TThread)
private
[...]
protected
procedure Execute(); override;
public
{**
* Constructor de la clase.
* @param string FileSystemEntryName Nombre del directorio a monitorizar.
* @param Boolean WatchSubTree Monitorizar también los subdirectorios.
*}
constructor Create(FileSystemEntryName: string; WatchSubTree: Boolean = True);
destructor Destroy(); reintroduce;
procedure Free();
{**
* Inicia la monitorización en un hilo separado.
*}
procedure Start();
{**
* Para la monitorización del directorio.
*}
procedure Stop();
{**
* @property string WatchedPath Directorio que se está monitorizando. Cada
* vez que se cambia se resetean todos los contadores, se para el hilo de ejecución
* y se vuelve a iniciar en caso de que estuviese activo.
*}
property WatchedPath: string read fFileSystemEntryName write setFileSystemEntryName;
property WatchSubtree: Boolean read fWatchSubtree write setWatchSubtree;
{**
* @property Cardinal ChangesCount Número de cambios en el sistema de archivos.
*}
property ChangesCount: Cardinal read fChangesCount;
{**
* @property TDateTime Fecha y hora del último cambio en el sistema de archivos.
*}
property LastChangeAt: TDateTime read fLastChangeAt;
{**
* @event TFileSystemChangeEvent OnFileSystemChange Evento que se produce cada
* vez que hay un cambio en el sistema de archivos.
*}
property OnFileSystemChange: TFileSystemChangeEvent read fFileSystemChangeEvent write fFileSystemChangeEvent;
{**
* Eventos que se producen cada vez que hay un cambio en el sistema de archivos
* sólo para archivos (no para directorios):
*
* @event TFileChangeEvent OnFileAdded Se lanza cuando se añade un archivo.
* @event TFileChangeEvent OnFileRemoved Se lanza cuando se borra un archivo.
* @event TFileChangeEvent OnFileModified Se lanza cuando se modifica un archivo.
* @event TFileRenamedEvent OnFileRenamed Se lanza cuando se renombra un archivo.
*}
property OnFileAdded: TFileChangeEvent read fFileAddedEvent write fFileAddedEvent;
property OnFileRemoved: TFileChangeEvent read fFileRemovedEvent write fFileRemovedEvent;
property OnFileModified: TFileChangeEvent read fFileModifiedEvent write fFileModifiedEvent;
property OnFileRenamed: TFileRenamedEvent read fFileRenamedEvent write fFileRenamedEvent;
{**
* Eventos que se producen cada vez que hay un cambio en el sistema de archivos
* sólo para directorios (no para archivos):
*
* @event TFileChangeEvent OnDirectoryAdded Se lanza cuando se añade un directorio.
* @event TFileChangeEvent OnDirectoryRemoved Se lanza cuando se borra un directorio.
* @event TFileChangeEvent OnDirectoryModified Se lanza cuando se modifica un directorio.
* @event TFileRenamedEvent OnDirectoryRenamed Se lanza cuando se renombra un directorio.
*}
property OnDirectoryAdded: TFileChangeEvent read fDirectoryAddedEvent write fDirectoryAddedEvent;
property OnDirectoryRemoved: TFileChangeEvent read fDirectoryRemovedEvent write fDirectoryRemovedEvent;
property OnDirectoryModified: TFileChangeEvent read fDirectoryModifiedEvent write fDirectoryModifiedEvent;
property OnDirectoryRenamed: TFileRenamedEvent read fDirectoryRenamedEvent write fDirectoryRenamedEvent;
end;
Como os habréis dado cuenta, este código está incompleto, faltan los datos privados, así que no copiéis y peguéis directamente. Lo mejor es bajarse el código fuente y la aplicación de ejemplo:
Descargar TFileSystemWatcher
Lo interesante de esta aplicación es que se puede sacar la clase TFileSystemWatcher del archivo FileSystemWatcher.pas y se puede incluir en cualquier proyecto que requiera monitorizar una o varias zonas del sistema de archivos. Por ejemplo, para hacer un buscador un poco más eficiente que el que trae el Windows.
La licencia de este software es Creative Commons 2.5 Reconocimiento – Compartir igual, así que esta clase se puede utilizar para lo que más os guste sin restricciones. Quizás en próximas versiones me pase a la GPL aunque todavía no la he estudiado lo suficiente (¿cuál es mejor, esta o la GPL?).
Y eso es todo, por el momento. Ahora intentaré continuar con otro proyecto que tengo en mente haciendo uso de esta clase (pues sí, ese buscador más eficiente que el que trae Windows al estilo Google Desktop… si, venga, vale, ya lo han hecho y funciona bien. Pero yo lo hago por aprender).
Y vosotros, si queréis, podéis probar el aparatín y me contáis
.