36

When a change is made within a directory on a Windows system, I need a program to be notified immediately of the change.

Is there some way of executing a program when a change occurs?

I'm not a C/C++/.NET programmer, so if I could set up something so that the change could trigger a batch file then that would be ideal.

Liam
  • 19,819
  • 24
  • 83
  • 123
  • It can be done with VBScript and WMI, see this implementation http://www.go-geek.com/tips-n-tricks/monitor-directory-for-new-files-with-wsh.html – Pradeep Aug 07 '12 at 13:57

8 Answers8

25

Use a FileSystemWatcher like below to create a WatcherCreated Event().

I used this to create a Windows Service that watches a Network folder and then emails a specified group on arrival of new files.

    // Declare a new FILESYSTEMWATCHER
    protected FileSystemWatcher watcher;
    string pathToFolder = @"YourDesired Path Here";

    // Initialize the New FILESYSTEMWATCHER
    watcher = new FileSystemWatcher {Path = pathToFolder, IncludeSubdirectories = true, Filter = "*.*"};
    watcher.EnableRaisingEvents = true;
    watcher.Created += new FileSystemEventHandler(WatcherCreated);

    void WatcherCreated(object source , FileSystemEventArgs e)
    {
      //Code goes here for when a new file is detected
    }
Derek Pollard
  • 6,953
  • 6
  • 39
  • 59
Refracted Paladin
  • 12,096
  • 33
  • 123
  • 233
  • 2
    I know you post states you are not a .NET programmer but with a copy of Free Visual Studio Express and the code I posted you are %80 af the way there. Stack OverFlow can probably get you the other %20. Depending on what you want to do with the detected file this is a very simple solution to implement and deploy. If you are interested I can elaborate my post to the who Window Service Creation. – Refracted Paladin Apr 17 '09 at 16:20
  • Thanks, I haven't used C# in a few years but if it is the best tool for the job then it is worth the extra effort. I'll set up Visual C# Express Edition. Thank you. – Liam Apr 17 '09 at 16:25
  • isnt it possible to use in PowerShell since its .NET ? you dont need visual studio at all. – v.oddou Sep 30 '14 at 07:41
  • 1
    It is worth noting here, that .net's own FileSystemWatcher is not 100% reliable. It may fail to react when there are a lot of changes to the folder being watched (like a few hundred files incoming at once). See http://stackoverflow.com/a/13917670/1128104 for a good explanation – buddybubble Nov 04 '15 at 07:32
  • 1
    I think you're missing "Watcher.EnableRaisingEvents = true;". Also you're inconsistent about "watcher" vs. "Watcher". – RenniePet Apr 30 '16 at 14:26
  • As for today, .Net v4.6.1 requires setting additional attributes: EnableRaisingEvents = true and NotifyFilter = NotifyFilters.FileName – Hasan Baidoun Oct 31 '17 at 16:23
10

FileSystemWatcher is the right answer except that it used to be that FileSystemWatcher only worked for a 'few' changes at a time. That was because of an operating system buffer. In practice whenever many small files are copied, the buffer that holds the filenames of the files changed is overrun. This buffer is not really the right way to keep track of recent changes, since the OS would have to stop writing when the buffer is full to prevent overruns.

Microsoft instead provides other facilities (EDIT: like change journals) to truly capture all changes. Which essentially are the facilities that backup systems use, and are complex on the events that are recorded. And are also poorly documented.

A simple test is to generate a big number of small files and see if they are all reported on by the FileSystemWatcher. If you have a problem, I suggest to sidestep the whole issue and scan the file system for changes at a timed interval.

Arturo Hernandez
  • 2,749
  • 3
  • 28
  • 36
6

If you want something non-programmatic try GiPo@FileUtilities ... but in that case the question wouldn't belong here!

Rob Walker
  • 46,588
  • 15
  • 99
  • 136
  • True, this question might be more appropriate for superuser or even serverfault, but this answer does directly answer the OP's question, "Is there some way of executing a program when a change occurs?". – Pat Jul 17 '12 at 17:04
  • GiPo@FileUtilities seems to have been taken down now, but http://www.myassays.com/folder-poll does something similar if you need something non-programmatic. – Mister Cook Sep 05 '16 at 10:23
3

This question helped me a lot to understand the File Watcher System. I implemented ReadDirectoryChangesW to monitor a directory and all its sub directories and get the information about change in those directories.

I have written a blog post on the same, and I would like to share it so it may help someone who land up here for the same problem.

Win32 File Watcher Api to monitor directory changes.

Neha
  • 1,751
  • 14
  • 36
3

I came on this page while searching for a way to monitor filesystem activity. I took Refracted Paladin's post and the FileSystemWatcher that he shared and wrote a quick-and-dirty working C# implementation:

using System;
using System.IO;

namespace Folderwatch
{
    class Program
    {
        static void Main(string[] args)
        {

            //Based on http://stackoverflow.com/questions/760904/how-can-i-monitor-a-windows-directory-for-changes/27512511#27512511
            //and http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

            string pathToFolder = string.Empty;
            string filterPath = string.Empty;
            const string USAGE = "USAGE: Folderwatch.exe PATH FILTER \n\n e.g.:\n\n Folderwatch.exe c:\\windows *.dll";

            try
            {
                pathToFolder = args[0];

            }
            catch (Exception)
            {
                Console.WriteLine("Invalid path!");
                Console.WriteLine(USAGE);
                return;
            }

            try
            {
                filterPath = args[1];
            }
            catch (Exception)
            {
                Console.WriteLine("Invalid filter!");
                Console.WriteLine(USAGE);
                return;

            }

            FileSystemWatcher watcher = new FileSystemWatcher();

            watcher.Path = pathToFolder;
            watcher.Filter = filterPath;

            watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | 
                NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | 
                NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;

            // Add event handlers.
            watcher.Changed += new FileSystemEventHandler(OnChanged);
            watcher.Created += new FileSystemEventHandler(OnChanged);
            watcher.Deleted += new FileSystemEventHandler(OnChanged);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);


            // Begin watching.
            watcher.EnableRaisingEvents = true;

            // Wait for the user to quit the program.
            Console.WriteLine("Monitoring File System Activity on {0}.", pathToFolder);
            Console.WriteLine("Press \'q\' to quit the sample.");
            while (Console.Read() != 'q') ;

        }

        // Define the event handlers. 
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is changed, created, or deleted.
            Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
        }

        private static void OnRenamed(object source, RenamedEventArgs e)
        {
            // Specify what is done when a file is renamed.
            Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
        }
    }
}

To use this, download Visual Studio (Express will do). The create a new C# console application called Folderwatch and copy and paste my code into your Program.cs.

As an alternative you could use Sys Internals Process Monitor: Process Monitor It can monitor the file system and a bunch more.

Jeff Davis
  • 4,736
  • 4
  • 38
  • 44
Eric
  • 2,861
  • 6
  • 28
  • 59
3

Use a FileSystemWatcher

SQLMenace
  • 132,095
  • 25
  • 206
  • 225
2

There is no utility or program the comes with Windows to do it. Some programming required.

As noted in another answer, .NET's FileSystemWatcher is the easiest approach.

The native API ReadDirectoryChangesW is rather harder to use (requires an understanding of completion ports).

Richard
  • 106,783
  • 21
  • 203
  • 265
1

After scouring github for several hours looking for FileSystemWatcher code as directed here, I found the following pages which have several, but similar, alternatives that deal with FileSystemWatcher's shortcomings (also mentioned in some of the answers):

https://github.com/theXappy/FileSystemWatcherAlts

A comparison table of which alternative works better for each scenario with a general rule of thumb at the bottom that explains which alternative to use in which situation:

https://github.com/theXappy/FileSystemWatcherAlts/blob/master/AltComparison.md

It's easily implemented or modified. If your project is already utilizing FileSytemWatcher you can simply change this:

FileSystemWatcher sysMonitor = new FileSystemWatcher(@"C:\");

To any of these:

IFileSystemWatcher sysMonitor = new FileSystemRefreshableWatcher(@"C:\");
IFileSystemWatcher sysMonitor = new FileSystemAutoRefreshingWatcher(@"C:\");
IFileSystemWatcher sysMonitor = new FileSystemPoller(pollingInterval: 500,path: @"C:\");
IFileSystemWatcher sysMonitor = new FileSystemOverseer(pollingInterval: 500, path: @"C:\");
Sum None
  • 2,164
  • 3
  • 27
  • 32