Hi Dare,
I don't think I ever quite figured it out, but did get this 'file monitor' working -- note that it's two separate source files
; "filemon-incs.pb"
Code: Select all
; PureBasic Visual Designer v3.72
;- Window Constants
;
#Window_0 = 0
;- Gadget Constants
;
#Gadget_1 = 0
#Gadget_0 = 1
#Gadget_2 = 2
#Gadget_3 = 3
#Gadget_4 = 4
#Gadget_5 = 5
#Gadget_6 = 6
Procedure Open_Window_0()
If OpenWindow(#Window_0, 0, 0, 440, 410, #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered , "New File Monitor - Hi-Toro 2003 (Public Domain: spread freely!)")
If CreateGadgetList(WindowID())
ListIconGadget(#Gadget_1, 20, 30, 400, 130, "Choose drives to monitor", 400 - (GetSystemMetrics_ (#SM_CXEDGE) * 2), #PB_ListIcon_CheckBoxes)
Frame3DGadget(#Gadget_0, 10, 10, 420, 160, "Drives to monitor")
Frame3DGadget(#Gadget_2, 10, 180, 420, 160, "Files added to selected drives during monitoring")
ListViewGadget(#Gadget_3, 20, 200, 400, 130)
ButtonGadget(#Gadget_4, 10, 350, 160, 30, "Monitor selected drives")
ButtonGadget(#Gadget_5, 180, 350, 160, 30, "Save list of files added...")
ButtonGadget(#Gadget_6, 350, 350, 80, 30, "Reset")
CreateStatusBar (0, WindowID ())
EndIf
EndIf
EndProcedure
; filemon.pb
Code: Select all
; PureBasic Visual Designer v3.72
IncludeFile "filemon-incs.pbi"
Open_Window_0()
DisableGadget (#Gadget_5, 1)
Procedure GetDriveList ()
Structure Drives
name.s
EndStructure
NewList disk.Drives ()
ResetList (disk ())
; Stupid, stupid Windows...
AllocateMemory (0, 255)
result = GetLogicalDriveStrings_ (255, MemoryID ())
If result > 255
ReAllocateMemory (0, result)
GetLogicalDriveStrings_ (result, MemoryID ())
EndIf
If result
For a = 0 To result - 1
byte = PeekB (MemoryID () + a)
If byte
drive$ = drive$ + Chr (byte)
Else
AddElement (disk ())
disk ()\name = drive$
drive$ = ""
EndIf
Next
FreeMemory (0)
ProcedureReturn #TRUE
Else
FreeMemory (0)
ProcedureReturn #FALSE
EndIf
EndProcedure
If GetDriveList ()
ResetList (disk ())
While NextElement (disk ())
AddGadgetItem (#Gadget_1, -1, disk ()\name)
Wend
EndIf
Structure FileList
entry.s
drive.s
EndStructure
NewList files.FileList ()
Procedure CountFiles (dir$, recursecount, drive$)
If Right (dir$, 1) <> "\"
dir$ = dir$ + "\"
EndIf
If ExamineDirectory (recursecount, dir$, "*.*")
Repeat
entry = NextDirectoryEntry ()
file$ = dir$ + DirectoryEntryName ()
; File...
If entry = 1
AddElement (files ())
files ()\entry = file$
files ()\drive = drive$
Else
; Folder...
If entry = 2
folder$ = DirectoryEntryName ()
If folder$ <> "." And folder$ <> ".."
If Right (folder$, 1) <> "\"
folder$ = folder$ + "\"
EndIf
folder$ = dir$ + folder$
AddElement (files ())
files ()\entry = folder$
files ()\drive = drive$
CountFiles (folder$, recursecount + 1, drive$)
UseDirectory (recursecount)
EndIf
EndIf
EndIf
Until entry = 0
EndIf
EndProcedure
NewList files2.FileList ()
NewList diffs.FileList ()
Procedure CountFiles2 (dir$, recursecount, drive$)
If Right (dir$, 1) <> "\"
dir$ = dir$ + "\"
EndIf
If ExamineDirectory (recursecount, dir$, "*.*")
Repeat
entry = NextDirectoryEntry ()
file$ = dir$ + DirectoryEntryName ()
; File...
If entry = 1
AddElement (files2 ())
files2 ()\entry = file$
files2 ()\drive = drive$
Else
; Folder...
If entry = 2
folder$ = DirectoryEntryName ()
If folder$ <> "." And folder$ <> ".."
If Right (folder$, 1) <> "\"
folder$ = folder$ + "\"
EndIf
folder$ = dir$ + folder$
AddElement (files2 ())
files2 ()\entry = folder$
files2 ()\drive = drive$
CountFiles2 (folder$, recursecount + 1, drive$)
UseDirectory (recursecount)
EndIf
EndIf
EndIf
Until entry = 0
EndIf
EndProcedure
Structure SelectedDisk
name.s
EndStructure
NewList selected.SelectedDisk ()
#WAIT_FAILED = $FFFFFFFF
#WAIT_OBJECT_0 = $0
#WAIT_ABANDONED = $80
#WAIT_TIMEOUT = $102
Repeat
e = WaitWindowEvent ()
Select e
Case #PB_Event_CloseWindow
End
Case #PB_Event_Gadget
Select EventGadgetID ()
Case #Gadget_4
ClearList (selected ())
seld = 0
For check = 0 To CountGadgetItems (#Gadget_1) - 1
If GetGadgetItemState (#Gadget_1, check) & #PB_ListIcon_Checked
AddElement (selected ())
selected ()\name = GetGadgetItemText (#Gadget_1, check, 0)
seld = seld + 1
EndIf
Next
If seld
ClearGadgetItemList (#Gadget_3)
DisableGadget (#Gadget_4, #TRUE)
StatusBarText (0, 0, "Compiling file list -- please wait...")
Dim Handles (seld)
ResetList (selected ())
hcount = 0
While NextElement (selected ())
Handles (hcount) = FindFirstChangeNotification_ (selected ()\name, #TRUE, #FILE_NOTIFY_CHANGE_FILE_NAME | #FILE_NOTIFY_CHANGE_DIR_NAME)
ClearList (files ())
CountFiles (selected ()\name, 0, selected ()\name)
hcount = hcount + 1
Wend
DisableGadget (#Gadget_4, #FALSE)
StatusBarText (0, 0, "")
;ResetList (files ())
;While NextElement (files ())
; Debug files ()\drive + " -- " + files ()\entry
;Wend
ResetList (selected ())
While NextElement (selected ())
selected ()\name
Wend
If hcount
SetGadgetText (#Gadget_4, "Stop monitoring selected drives")
DisableGadget (#Gadget_1, #TRUE)
DisableGadget (#Gadget_3, #TRUE)
DisableGadget (#Gadget_6, #TRUE)
changes = 0
Repeat
e = WindowEvent ()
result = WaitForMultipleObjects_ (hcount, @Handles (), #FALSE, 10)
; Valid result! See WaitForMultipleObjects docs to explain bounds check!
If result => #WAIT_OBJECT_0 And result <= #WAIT_OBJECT_0 + hcount - 1
;Debug "Change in monitored folders/sub-folders!"
changes = changes + 1
; Reset the handle that caused the notification (again, see docs)...
FindNextChangeNotification_ (Handles (result - #WAIT_OBJECT_0))
Else
; ; Result failed!
;
If result = #WAIT_FAILED
MessageRequester ("New file monitor", "One or more selected drives unavailable!", #MB_ICONWARNING)
For check = 0 To CountGadgetItems (#Gadget_1) - 1
SetGadgetItemState (#Gadget_1, check, 0)
Next
ClearGadgetItemList (#Gadget_1)
ClearGadgetItemList (#Gadget_3)
ClearList (disk ())
If GetDriveList ()
ResetList (disk ())
While NextElement (disk ())
AddGadgetItem (#Gadget_1, -1, disk ()\name)
Wend
EndIf
EndIf
EndIf
Until e = #PB_EventGadget Or result = #WAIT_FAILED
For a = 0 To seld - 1
FindCloseChangeNotification_ (Handles (a))
Next
DisableGadget (#Gadget_1, #FALSE)
DisableGadget (#Gadget_3, #FALSE)
DisableGadget (#Gadget_6, #FALSE)
SetGadgetText (#Gadget_4, "Monitor selected drives")
If changes
ResetList (selected ())
While NextElement (selected ())
ClearList (files2 ())
CountFiles2 (selected ()\name, 0, selected ()\name)
Wend
ClearList (diffs ())
ResetList (files ())
While NextElement (files ())
ResetList (files2 ())
While NextElement (files2 ())
If files ()\entry = files2 ()\entry
DeleteElement (files2 ())
LastElement (files2 ())
EndIf
Wend
Wend
ResetList (files2 ())
While NextElement (files2 ())
If FileSize (files2 ()\entry) <> -1
AddGadgetItem (#Gadget_3, -1, files2 ()\entry)
; Debug files2 ()\drive + " -- " + files2 ()\entry
EndIf
Wend
EndIf
EndIf
EndIf
Case #Gadget_6
For check = 0 To CountGadgetItems (#Gadget_1) - 1
SetGadgetItemState (#Gadget_1, check, 0)
Next
ClearGadgetItemList (#Gadget_1)
ClearGadgetItemList (#Gadget_3)
ClearList (disk ())
If GetDriveList ()
ResetList (disk ())
While NextElement (disk ())
AddGadgetItem (#Gadget_1, -1, disk ()\name)
Wend
EndIf
EndSelect
EndSelect
ForEver
Although you can determine which files have been added using some NT-specific APIs, there's no way to determine what's new on 9x without comparing the before-and-after state as far as I'm aware (so that's what this program does)...
Finding out which program owns a file is pretty advanced, low-level stuff I've never figured out (have a look at
www.sysinternals.com for their 'handle' or 'Process Explorer' programs, which can do this, though they don't explain how)...
I can't really remember exactly how this program works now!