WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Samples from Users
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

How to Watch for Files and Then Do Something

Keywords:   watch for files


WMI Sample

The following query watches for notification that a file has been added or deleted to/from a folder.
;The following query watches for notification that a file has been added or deleted to/from a folder.
strComputer = "."
objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" : strComputer : "\root\cimv2")
colMonitoredEvents = objWMIService.ExecNotificationQuery (`SELECT * FROM  __InstanceOperationEvent WITHIN 10 WHERE Targetinstance ISA 'CIM_DirectoryContainsFile' and TargetInstance.GroupComponent= 'Win32_Directory.Name="c:\\\\Temp"'`)
While @TRUE
    objLatestEvent = colMonitoredEvents.NextEvent
     class = objLatestEvent.Path_.Class
     component = objLatestEvent.TargetInstance.PartComponent
     file = StrReplace( StrTrim(ItemExtract( 2, component, '=' )), '\\', '\' )
     Select @TRUE
        Case class == "__InstanceCreationEvent"
            Pause("A new file was just created:", file )
            Break
        Case class == "__InstanceDeletionEvent"
             Pause("A file was just deleted:", file )
            Break
    EndSelect
EndWhile


DLLCall Sample

;********************************************************************
;  This routine watches three different folders to see when a file
;  is created.  It processes the files, then continues watching.
;  It can easily be modified to watch a different number of folders.
;
;  Assumption:   The folders are usually empty.  When a file is dropped 
;  into them, we process the file and then either delete it or move it 
;  somewhere else.  This simplifies processing since we can look in the 
;  directories and grab anything we find there.  If this is not the case 
;  you'll need to add code that decides which files you want to operate on.
;
;  The process displays a window with a STOP button.
;  Push the button to stop processing.
;********************************************************************


;**********************************************************************
;  Create an array to hold the names of the folders you want to watch,
;  then put the folder names into the array.
;********************************************************************
WatchDir = ArrDimension(3) ; limit 64  (The maximum number of object handles is MAXIMUM_WAIT_OBJECTS.)

WatchDir[0] = "C:\Windows\Desktop\WatchOne"  
WatchDir[1] = "C:\Windows\Desktop\WatchTwo"  
WatchDir[2] = "C:\Windows\Desktop\WatchThree" 

;********************************************************************
;  The remainder of the routine will process as many directories
;  as you have defined above.  (The array size tells it how many.)
;********************************************************************
NumberOfFolders = ArrInfo(WatchDir,1)
FolderArrayTop  = NumberOfFolders - 1

;********************************************************************
;  Function to get an error message after an API error.
;  Pass it the code returned by DllLastError()
;********************************************************************
#DefineFunction SystemMessage(Err)
  Buffer = BinaryAlloc(256)
  BinaryEodSet(Buffer,255)
  if  0 == DllCall(StrCat(DirWindows(1),"Kernel32.dll"),long:"FormatMessageA",long:4096,long:0,long:Err,long:0,lpbinary:Buffer,long:256,long:0)
     Text = StrCat("Error #",Err)
  else
     Text = BinaryPeekStr(Buffer,0,256)
  endif
  BinaryFree(Buffer)
  Return Text
#EndFunction

;********************************************************************
;  Initialize the API.
;  Note.. The "MsgWaitForMultipleObjects" API, which we call below
;         requires a pointer to an array of handles.  We manage this
;         by poking the handles into a binary buffer, and passing
;         the buffer as "lpbinary".
;********************************************************************
User32   = DLLLoad(StrCat(DirWindows(1),"User32.DLL"))
Kernel32 = DllLoad(strcat(DirWindows(1),"KERNEL32.DLL"))
Handles  = ArrDimension(NumberOfFolders)
HandleBinary = BinaryAlloc(NumberOfFolders*4)
For X = 0 to FolderArrayTop
   Handles[X] = DLLCALL(Kernel32,long:"FindFirstChangeNotificationA",lpstr:WatchDir[X],long:1,long:1)
   if Handles[X] == -1          ; -1 is an error status.  Cancel processing
       Err = DllLastError()
       Message(StrCat("Error ",Err),StrCat("Error... Directory = ",WatchDir[X],@CRLF,SystemMessage(Err)))
       for Y = 0 to (X-1)
           DLLCALL(Kernel32,long:"FindCloseChangeNotification",long:Handles[Y])
       next
       DllFree(Kernel32)
       DllFree(User32)
       BinaryFree(HandleBinary)
       Exit
   endif
   BinaryPoke4(HandleBinary,X*4,Handles[X])
Next

;********************************************************************
;  A box with a STOP button
;********************************************************************
BoxesUp("25,25,400,150",@NORMAL)
BoxCaption(1,"Waiting")
BoxDrawText(1,"50,300,700,800","Watching Directories.",@TRUE,0)
BoxButtonDraw(1,1,"STOP","600,200,900,800")

;********************************************************************
;  The Wait Loop
;********************************************************************
Err = 0;
while (1)
    ; -----------------------------------------------------------------------------
    ; Note:  In the following call, "-1" means "No Timeout".  
    ; If you want a timeout you can substitute a time in ms.  (1000 = 1 second.)   
    ; WaitStatus == 258 indicates a timeout.
    ;------------------------------------------------------------------------------
    WaitStatus = DLLCall(User32,long:"MsgWaitForMultipleObjects",long:NumberOfFolders,lpbinary:HandleBinary,long:0,long:-1,long:255)
    Yield()   ; Process any queued system events.
    ; -----------------------------------------------------------------------------
    ;  Test the button.  If the user pressed it, we exit.
    ;------------------------------------------------------------------------------
    if BoxButtonStat(1,1) then break
    ; -----------------------------------------------------------------------------
    ;  A return status of -1 indicates an error.
    ;------------------------------------------------------------------------------
    if WaitStatus < 0 then
        Err = DllLastError()
        Message(StrCat("Error ",Err),StrCat("Error while waiting for new files.",@CRLF,SystemMessage(Err)))
        break
    endif
    ; -----------------------------------------------------------------------------
    ;  If a directory changed the return status is its index in the Handle Array.
    ;  Process the directories that changed.
    ;------------------------------------------------------------------------------
    if WaitStatus < NumberOfFolders
         FileList = FileItemize(StrCat(WatchDir[WaitStatus],"\*.*"))
         FileCount = ItemCount(FileList,@TAB)
         For X = 1 to FileCount
             NewFile = ItemExtract(X,FileList,@TAB)
             ;--------------------------------------------------------------------
             ; Here we can do whatever we want with the new file.
             ; Then (given the assumptions made for this routine)
             ; we delete or move it, so it won't be processed again.
             ;--------------------------------------------------------------------
             Message(StrCat("New File in ",WatchDir[WaitStatus]),StrCat("New File: ",NewFile))
             FileDelete(StrCat(WatchDir[WaitStatus],"\",NewFile))
         Next
         ;--------------------------------------------------------------------
         ; After the API sees a change in a folder, we must tell it to
         ; keep watching for another change.  (Zero status = an error.)
         ;--------------------------------------------------------------------
         if 0 == DLLCALL(Kernel32,long:"FindNextChangeNotification",long:Handles[WaitStatus])
            Err = DllLastError()
            Message(StrCat("Error ",Err),StrCat("Error... Directory = ",WatchDir[WaitStatus],@CRLF,SystemMessage(Err)))
            break
         endif  
    endif
endwhile

;********************************************************************
;   Clean up on exit
;********************************************************************
BinaryFree(HandleBinary)
For X = 1 to FolderArrayTop
    DLLCALL(Kernel32,long:"FindCloseChangeNotification",long:Handles[X])
next
DllFree(Kernel32)
DllFree(User32)
return


Article ID:   W15288
File Created: 2014:02:21:11:38:22
Last Updated: 2014:02:21:11:38:22