I asked before if people could find any possible bugs in one of the units I wrote. In the meantime I've updated another unit that I'm working on and I want to be sure it's flawless too, but I just run out of time to test it thoroughly myself...
The unit is at http://www.workshop-alex.org/Sources/TrayIcon/untExtraInterfaces.html
and basically, it's a wrapper around standard Windows objects, like a mutex, a semaphore, a critical section, an event and since today, the FindXXXChangeNotification API. There's also some kind of timer and an unique number generator in it but they aren't too interesting right now.
So, well... I share this code here for the EE members and will reward any bug found. 100 points for a major bug, 50 for a minor and 20 for an interesting suggestion. Points will be divided between participants once 5 major bugs, 10 minor bugs or 25 suggestions (or combinations) have been found. First comes, first goes...
If no bugs are found then consider the reward for your tests the use of some very interesting interfaces in your code. ;-) Maybe you can find some good use for them. The code is free of charge, as reward for testing. :-)
I hope the code explains itself a bit. It's advanced Delphi code so not real beginners stuff. It should encapsulate the more complex Windows API functions.
About the critical section interface, if you say 'Blocking=False' then it's actually doing nothing! Just a trick to check if code runs better without a critical section. (Or when the use of a CS depends on some setting.)
The IFolderChange interface is the one I'm most interested in. I'll show a simple example here of it's usage.
TFormMain = class( TForm )
procedure FormCreate( Sender: TObject );
procedure FormDestroy( Sender: TObject );
procedure Add( const Value: string ); overload;
procedure Add( const Value: string; const Data: array of const ); overload;
procedure HasChanged( const Path: string );
procedure TFormMain.Add( const Value: string );
Memo.Lines.Add( Value );
procedure TFormMain.Add( const Value: string; const Data: array of const );
Add( Format( Value, Data ) );
procedure TFormMain.FormCreate( Sender: TObject );
FolderChange := NewFolderChange( IncludeTrailingBackslash( ExtractFilePath( ParamStr( 0 ) ) + 'XML), HasChanged, FILE_NOTIFY_CHANGE_FILE_NA
ME or FILE_NOTIFY_CHANGE_SIZE );
procedure TFormMain.FormDestroy( Sender: TObject );
FolderChange := nil;
procedure TFormMain.HasChanged( const Path: string );
Add( 'Files changed in "%s".', [ Path ] );
if ( FindFirst( Path + '*.*', faAnyFile - faDirectory, SearchRec ) = 0 ) then begin
Source := Path + SearchRec.Name;
Sleep( 0 );
TFileStream.Create( Source, fmOpenReadWrite + fmShareExclusive ).Free; // Just to check if we can open the file exclusively.
DeleteFile( Source );
except on E: Exception do Add( E.Message );
until ( FindNext( SearchRec ) <> 0 );
FindClose( SearchRec );
Explanation: Above example creates a file notifier for a subfoler 'XML' in my application folder. Whenever a file is dumped in this folder, it should try to see if it can be opened exclusively and then just delete the file. (Actually, I will be processing the contents before deleting it.) Since the notifier only tells me that a change has occurred and doesn't tell me what has changed exactly, I will have to loop through all files. Not a big problem since I will process everything in this folder...
If it fails to process a file (because it's still open) then no worries. It will get processed when I get notified about the next change in this folder.
Do keep in mind though, the HasChanged method is NOT executed in the main thread but in a separate thread. As long as HasChanged is running, the system isn't notified about other file changes. I could synchronise this code with the main thread but this should be done from the HasChanged method. Problem is, this code is also supposed to work in console applications where the main thread doesn't have a messageloop. Without a messageloop, it's not possible to start some function in the main thread...
And if this unit or code has been useful for you, just post a note here too. Or at the member feedback in my profile, if you want to inflate my ego... :-)
Remember, I am interested in bugs in this code and just don't have enough time to test it thoroughly myself. (Besides, no developer should test his own code!)