🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #8276

Monitoring folder changes (FindFirstChangeNotification): Multiple f-ion calls

#8276
From: Vladimir Stefanovic
Date: Tue, 09 Nov 2004 15:30
209 lines
5627 bytes
Hi,

I found a class (BCB Journal, april 2001) that monitors for
folder changes, but I cannot control it as I want. I want it
to react only when some file in folder (not subfolders) is:

(1) created
(2) changed
(3) deleted

ie, flags = FILE_NOTIFY_CHANGE_FILE_NAME |
   FILE_NOTIFY_CHANGE_LAST_WRITE;

But the problem is, that the function MyAction() is
executed 2 or 4 times for file creation, and 2 times for
file change. Only when the file is deleted, the function
is executed once - as I wanted.

Is this normal?

--- code that prepares for notification ---

   TChangeNotification *note;

   __fastcall TForm1::TForm1(TComponent* Owner)
           : TForm(Owner)
   {
      note = new TChangeNotification ( this );
      note->Folder =  "C:\\Test";
      note->WatchSubFolders = false;
      note->OnChange = MyAction;
      note->Start();
   }

   __fastcall TForm1::~TForm1()
   {
      note->Stop();
      delete note;
   }

   void __fastcall TForm1::MyAction(TObject* Sender)
   {
      Memo1->Lines->Add( "Changed!" );
   }

I tried to include the flags (see below) but, the result is
not changed. I also tried to wait a while and ProcessMessages
in a loop but the result was still the same.

   bool InProgress = false;

   void __fastcall TForm1::MyAction(TObject* Sender)
   {
      if ( InProgress )
         return;
      try
      {
         InProgress = true;
         Memo1->Lines->Add( "Changed!" );
      }
      __finally
      {
         InProgress = false;
      }
   }

The Start() & Stop() which are public for the class, if I use
in MyAction(), instead of InProgress, stucks the app. I think
that's because the Stop() doesn't make any checks, just deletes
the thread (see the class).

I feel that I have to modify the class, but what part? Or I should
try to use Borland's solution I saw once somewhere in borland
develpoers network.

--- class ---

DWORD dir_ch_not_flags = FILE_NOTIFY_CHANGE_FILE_NAME |
                         FILE_NOTIFY_CHANGE_LAST_WRITE;

__fastcall TChangeNotification::TChangeNotification(TComponent *owner)
: TComponent(owner)
{
   onChange = 0;
   onError = 0;
   thread = 0;
   watchSubFolders = False;
}
__fastcall TChangeNotification::~TChangeNotification()
{
   delete thread;
}
void __fastcall TChangeNotification::Start()
{
   if ( thread == 0 )
      thread = new TCNThread(this);
}
void __fastcall TChangeNotification::Stop()
{
   delete thread;
   thread = 0;
}
void __fastcall TChangeNotification::SetFolder(String aFolder)
{
   if ( thread != 0 )
   {
      Stop();
      folder = aFolder;
      Start();
   }
   else
      folder = aFolder;
}
void __fastcall TChangeNotification::SetOnChange(TNotifyEvent event)
{
   if ( thread != 0 )
   {
      thread->Suspend();
      onChange = event;
      thread->Resume();
   }
   else
      onChange = event;
}
void __fastcall TChangeNotification::SetOnError(TNotifyEvent event)
{
   if ( thread != 0 )
   {
      thread->Suspend();
      onError = event;
      thread->Resume();
   }
   else
      onError = event;
}
void __fastcall TChangeNotification::SetWatchSubFolders(bool watch)
{
   if ( thread != 0 )
   {
      Stop();
      watchSubFolders = watch;
      Start();
   }
   else
      watchSubFolders = watch;
}
__fastcall
TChangeNotification::TCNThread::TCNThread(TChangeNotification *owner)
: TThread(false), owner(owner)
{
   handle = 0;
}
__fastcall TChangeNotification::TCNThread::~TCNThread()
{
   Terminate();

   if ( handle != 0 )
   {
      FindCloseChangeNotification( handle );
      handle = 0;
   }
}
void __fastcall TChangeNotification::TCNThread::Execute()
{
   handle = FindFirstChangeNotification( owner->Folder.c_str(),
owner->WatchSubFolders, dir_ch_not_flags );

   if ( handle == INVALID_HANDLE_VALUE )
   {
      Synchronize( Error );
      Terminate();
   }

   while ( !Terminated )
   {
      DWORD status = WaitForSingleObject(handle, INFINITE);

      if ( status == WAIT_OBJECT_0 && Terminated == false )
      {
         Synchronize( Notify );
         if ( FindNextChangeNotification( handle ) == 0 )
         {
            Synchronize( Error );
            Terminate();
         }
      }
      else
         Terminate();
   }
}
void __fastcall TChangeNotification::TCNThread::Notify(void)
{
   if ( owner->OnChange ) owner->OnChange( owner );
}
void __fastcall TChangeNotification::TCNThread::Error(void)
{
   if ( owner->OnError ) owner->OnError( owner );
}
static inline void ValidCtrCheck(TChangeNotification *)
{
   new TChangeNotification( NULL );
}


--


Best regards,
Vladimir Stefanovic
Technical Details
Message-ID: <4190e2a3@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!newsprint.newsread.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,1dc9679112d7194f,start
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Vladimir Stefanovic" <spam@not.needed>
Newsgroups: borland.public.cppbuilder.nativeapi
Subject: Monitoring folder changes (FindFirstChangeNotification): Multiple f-ion calls
Date: Tue, 9 Nov 2004 16:30:14 +0100
Lines: 212
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 5.00.2314.1300
X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300
NNTP-Posting-Host: 213.137.116.237
Message-ID: <4190e2a3@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1100014243 213.137.116.237 (9 Nov 2004 07:30:43 -0700)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!newsprint.newsread.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail