C'est en réponse à une demande du forum.
Ce programme permet d'utiliser les notifications de Windows en cas de modification de fichier ou d'un répertoire. Il est basé sur les fonctions Wait de l'API. Ces fonctions étant bloquante pour le Thread qui les appellent, alors un Thread auxiliaire est créé pour gérer les attentes.
Utilisation : Saisir le répertoire dans le TEdit et cliquer sur le bouton 'Lancer !'
Source / Exemple :
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Panel1: TPanel;
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
TThreadSurveillance = class(TThread)
private
{ Déclarations privées }
ListeAjouts : TStrings;
HandleNotification : THandle;
CheminEnCours : String;
DateHeureVerification : TDateTime;
Procedure MiseAJourListe;
protected
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
Var CheminASurveiller : String = '';
ThreadSurveillance : TThreadSurveillance = Nil;
procedure TThreadSurveillance.Execute;
Var Chemin :Array[0..255]Of Char;
Infos :TSearchRec;
begin
// Initialisation ds données du Thread
ListeAjouts := TStringList.Create;
HandleNotification := INVALID_HANDLE_VALUE;
CheminEnCours := '';
// Boucle pincipale du Thread
While Not Terminated Do
Begin
// Le chemin demandé à changé => Changer la surveillance
If CheminASurveiller<>CheminEnCours
Then Begin
ListeAjouts.Clear;
// Une demande est en cours, on libère le Handle
If HandleNotification<>INVALID_HANDLE_VALUE
Then Begin
FindCloseChangeNotification(HandleNotification);
HandleNotification:=INVALID_HANDLE_VALUE;
ListeAjouts.Add('<FIN>');
End;
// Prise en compte de la nouvelle demande
CheminEnCours:=CheminASurveiller;
If CheminEnCours<>''
Then Begin
// Suppression du '\' final
CheminEnCours := ExcludeTrailingPathDelimiter(CheminEnCours);
// Création de la demande de notification
HandleNotification := FindFirstChangeNotification(
StrPCopy(Chemin,CheminEnCours), // Chemin à surveiler
False, // Ne pas surveiller les sous-répertoires
FILE_NOTIFY_CHANGE_FILE_NAME+FILE_NOTIFY_CHANGE_LAST_WRITE); // Surveiller les écriture et changement de noms
// Mémorisation de l'heure de la demande
DateHeureVerification:=Now;
ListeAjouts.Add('<DEBUT:'+CheminEnCours+'>');
End;
Synchronize(MiseAJourListe);
End;
// Une demande de notification est en cours
If HandleNotification<>INVALID_HANDLE_VALUE
Then Begin
// Il faut donc demander à Windows d'être prévenu en cas de modification
// La sortie de WaitForSingleObject est effectuée dans le cas d'une notification
// ou dans le cas d'un TimeOut. Il ne faut pas ici utiliser le timeout INFINITE
// sinon le thread risque d'être bloqué en permanence.
Case WaitForSingleObject(HandleNotification,200) Of
WAIT_OBJECT_0:Begin
// Dans le cas d'une notification il faut rechercher
// les fichiers modifiés depuis le dernier appel
ListeAjouts.Clear;
If FindFirst(CheminEnCours+PathDelim+'*.*',faAnyFile,Infos)=0
Then Begin
Repeat
// Le fichier à été modifié, on l'ajoute à la liste
If FileDateToDateTime(Infos.Time)>DateHeureVerification
Then Begin
{$IFDEF MSWINDOWS}
// FindData.CFileName n'est utilisable que sous Windows
ListeAjouts.Add(FormatDateTime('DD/MM/YYYY HH:NN:SS',FileDateToDateTime(Infos.Time))+'='+
StrPas(Infos.FindData.cFileName));
{$ENDIF}
{$IFDEF LINUX}
// Pour Linux le nom court est mémorisé
ListeAjouts.Add(FormatDateTime('DD/MM/YYYY HH:NN:SS',FileDateToDateTime(Infos.Time))+'='+
StrPas(Infos.Name));
{$ENDIF}
End;
Until FindNext(Infos)<>0;
FindClose(Infos);
// Ajout des fichiers modifiés dans le Memo
// Comme c'est un Thread, il n'est pas possible de modifier directement Memo1
Synchronize(MiseAJourListe);
End;
// Mémorisation de l'heure en cours pour le prochain test
DateHeureVerification:=Now;
End;
WAIT_TIMEOUT :;
End;
// Le handle doit être mis à jour pour pouvoir effectuer une nouvelle demande
FindNextChangeNotification(HandleNotification);
End;
End;
// Libération du Handle en cas de besoin
If HandleNotification<>INVALID_HANDLE_VALUE Then FindCloseChangeNotification(HandleNotification);
HandleNotification:=INVALID_HANDLE_VALUE;
// Libération des objets
ListeAjouts.Free;
end;
// Cette procédure ne doit être appelée que par l'intermédiaire de Synchronize
procedure TThreadSurveillance.MiseAJOurListe;
Begin
Form1.Memo1.Lines.AddStrings(ListeAjouts);
End;
// Création du Thread
procedure TForm1.FormCreate(Sender: TObject);
begin
ThreadSurveillance:=TThreadSurveillance.Create(False);
end;
// Libération du Thread
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
If ThreadSurveillance<>Nil
Then Begin
ThreadSurveillance.Terminate;
ThreadSurveillance.WaitFor;
End;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
CheminASurveiller:=Edit1.Text;
end;
end.
Conclusion :
A la compilation il y a un avertissement 'Le symbole FindData est propre à une plateforme', mais ce message peut être ignoré.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.