Page 1 of 1

KeepTrackOnDirs - Watching folders

Posted: Fri May 09, 2008 1:15 pm
by dige
hi guys, I often save files from emails, image editing, etc. and needed a tool
that collects such data. something like watch folders and subfolders.
per drag'n drop, the files can open quickly.

I've written my own and called it : KeepTrackOnDirs - have fun with it!

Create a watchfolder.ini, if you wanna use predefined settings...

Code: Select all

; Watch a folder and all subfolder for changes
; dige 5/2008
; Compile with ThreadSafe enabled!!

; #FILE_NOTIFY_CHANGE_FILE_NAME
; #FILE_NOTIFY_CHANGE_DIR_NAME
; #FILE_NOTIFY_CHANGE_ATTRIBUTES
; #FILE_NOTIFY_CHANGE_SIZE
; #FILE_NOTIFY_CHANGE_LAST_WRITE
; #FILE_NOTIFY_CHANGE_SECURITY

Structure WatchFolder
  Dir.s
  WaitMillisecs.l
  hChngObject.l
  ThreadID.l
  Flag.b
EndStructure

Structure FileList
  FileName.s
  FileSize.l
  Date_Created.l
  Date_Accessed.l
  Date_Modified.l
  Flag.b
EndStructure

Global NewList WF.WatchFolder()

Procedure   DragNDropFile()
  Protected File.s, Result.s
  
  For i = 0 To CountGadgetItems(1)-1
    If GetGadgetItemState(1, i) & #PB_ListIcon_Selected
      File = GetGadgetItemText(1, i)
      File = Trim(StringField( File, 2, ">" ))
      If File : Result + File + Chr(10) : EndIf
    EndIf
  Next i 
  
  If Result : DragFiles(Result) : EndIf
  
EndProcedure
Procedure   DoWatchFolder(*WF.WatchFolder)
  Protected NewList FL.FileList(), DirID.l, Found.b, File.s, Count.l
  
  Macro GetFileStuff
    FL()\FileSize      = FileSize (FL()\FileName)
    FL()\Date_Created  = GetFileDate( FL()\FileName, #PB_Date_Created )
    FL()\Date_Accessed = GetFileDate( FL()\FileName, #PB_Date_Accessed )
    FL()\Date_Modified = GetFileDate( FL()\FileName, #PB_Date_Modified )
  EndMacro
  
  
  With *WF
    DirID = ExamineDirectory(#PB_Any, \Dir, "*.*")  
    ; Add files
    If DirID
      While NextDirectoryEntry(DirID)
        If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File
          If AddElement( FL() )
            FL()\FileName      = \Dir + "\" + DirectoryEntryName(DirID)
            GetFileStuff
          Else
            ProcedureReturn
          EndIf
        EndIf
      Wend
      FinishDirectory(DirID)
    EndIf
    
    While \Flag = 0
      \hChngObject=FindFirstChangeNotification_(\Dir, #Null, #FILE_NOTIFY_CHANGE_FILE_NAME|#FILE_NOTIFY_CHANGE_SIZE|#FILE_NOTIFY_CHANGE_LAST_WRITE)
      
      If WaitForSingleObject_(\hChngObject, \WaitMillisecs) = 0
        Count = 0
        Repeat
          DirID = ExamineDirectory(#PB_Any, \Dir, "*.*")  
          ; check files
          If DirID
            ForEach FL()
              FL()\Flag = 0
            Next
            
            While NextDirectoryEntry(DirID)
              If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File
                Found = #False
                ForEach FL()
                  If FL()\FileName = \Dir + "\" + DirectoryEntryName(DirID)
                    Found = 1
                    
                    If FL()\FileSize <> FileSize (FL()\FileName) : Found = 2 : EndIf
                    If FL()\Date_Created <> GetFileDate( FL()\FileName, #PB_Date_Created )   : Found = 3 : EndIf
                    If FL()\Date_Accessed <> GetFileDate( FL()\FileName, #PB_Date_Accessed ) : Found = 4 : EndIf
                    If FL()\Date_Modified <> GetFileDate( FL()\FileName, #PB_Date_Modified ) : Found = 5 : EndIf
                    
                    File = FL()\FileName
                    GetFileStuff
                    FL()\Flag = Found
                  
                    Break
                  EndIf
                Next
                
                File = ""
                
                If Not Found
                  If AddElement( FL() )
                    FL()\FileName      = \Dir + "\" + DirectoryEntryName(DirID)
                    FL()\FileSize      = FileSize (FL()\FileName)
                    GetFileStuff
                    File = FL()\FileName
                    FL()\Flag = 6
                    Found = 6     ; New File
                  EndIf
                EndIf
              EndIf
              
              If File
                Select Found
                  Case 2     : File = "NewFileSize > " + File
                  Case 3,4,5 : File = "NewDate > " + File
                  Case 6     : File = "NewFile > " + File
                EndSelect
                
                If Found <> 1 : Count + 1 : AddGadgetItem( 1, -1, "[" + Str(\ThreadID) + "] " + File ) : EndIf
                File = ""
              EndIf
  
            Wend
            
            FinishDirectory(DirID)
            
            ForEach FL()
              If FL()\Flag = 0
                AddGadgetItem( 1, -1, "Deleted: " + FL()\FileName )
                DeleteElement( FL() )
                Count + 1
              EndIf
            Next
            
          Else
            Break 2
          EndIf
        Until Count = 0
      EndIf
      
      FindNextChangeNotification_(\hChngObject)
    Wend
    
    If \hChngObject
      FindCloseChangeNotification_(\hChngObject)
    EndIf
    
    ClearList( FL () )
    
    \ThreadID = 0
  EndWith
EndProcedure
Procedure   InitWatchFolder ( Dir.s )
  
  If Right(Dir, 1) = "\" : Dir = Left(Dir, Len(Dir) - 1) : EndIf
  DirID = ExamineDirectory(#PB_Any, Dir, "*.*")  
  
  If DirID
    AddElement( WF() )
    With WF()
      \Dir = Dir
      \WaitMillisecs = 2000; wait 1sec. to decrease cpu load
      \ThreadID = CreateThread(@DoWatchFolder(), @WF())
      ThreadPriority( \ThreadID,  1 ) ; decreas cpu load
    EndWith
    AddGadgetItem(1, -1, "Add: " + Dir )
    
    While NextDirectoryEntry(DirID)
      If DirectoryEntryType(DirID) = #PB_DirectoryEntry_Directory
        If DirectoryEntryName(DirID) <> "." And DirectoryEntryName(DirID) <> ".."
          InitWatchFolder( Dir + "\" + DirectoryEntryName(DirID) )
        EndIf
      EndIf
    Wend
    FinishDirectory(DirID)
  EndIf
EndProcedure
Procedure.b QuitWatchFolder()
  Protected Quit.b
  
  ForEach WF()
    If WF()\ThreadID And IsThread( WF()\ThreadID )
      WF()\Flag = 1
    EndIf
  Next
  
  TimeOut = ElapsedMilliseconds() + 50000
  Repeat
    Delay(200)
    Count = 0
    ForEach WF()
      If WF()\ThreadID
        Count + 1
      EndIf
    Next
  Until Count = 0 Or TimeOut < ElapsedMilliseconds()
  
  If Count = 0 : Quit = 1 : Else : Quit = 2 : EndIf
  AddGadgetItem(1, -1, "QuitCode: " + Str(Quit))
  
  ProcedureReturn Quit
EndProcedure

;{ MainLoop
If OpenWindow(0, 100, 200, 350, 400, "KeepTrackOnDirs by DiGe", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  If CreateGadgetList(WindowID(0))
    ListIconGadget( 1, 0, 0, 350, 380, "", 345, #PB_ListIcon_MultiSelect|#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect )
    ButtonGadget( 2, 0, 380, 100, 20, "Clear List" )
    ButtonGadget( 3, 100, 380, 100, 20, "Quit Watch" )
  EndIf
  
  #INIFILE = "WatchFolder.ini"
  Dir.s    = ""
  
  FileID = ReadFile( #PB_Any, #INIFILE )
  If FileID
    While Not Eof(FileID)
      Dir = ReadString( FileID )
      If Dir
        InitWatchFolder( Dir )
      EndIf
    Wend
    CloseFile(FileID)
    
  Else
    Dir = PathRequester( "WatchFolder", "" )
    If Dir : InitWatchFolder( Dir ) : EndIf
  EndIf
   
  AddGadgetItem( 1, -1, "Watching " + Str(CountList(WF())) + " Folder(s)")
  
  Repeat
    EventID.l = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      Quit = QuitWatchFolder()
    ElseIf EventID = #PB_Event_Gadget
        
      Select EventGadget()
        Case 1 : If EventType() = #PB_EventType_DragStart : DragNDropFile () : EndIf
        Case 2 : ClearGadgetItemList(1)  
        Case 3 : Quit = QuitWatchFolder()  
      EndSelect
    EndIf
  Until Quit
  While WindowEvent() : Wend
  Delay(1000)
EndIf
;}
End