简体   繁体   English

如何监视 Windows 目录的更改?

[英]How can I monitor a Windows directory for changes?

When a change is made within a directory on a Windows system, I need a program to be notified immediately of the change.当在 Windows 系统上的目录中进行更改时,我需要一个程序立即收到更改通知。

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.我不是 C/C++/.NET 程序员,所以如果我可以设置一些东西以便更改可以触发批处理文件,那将是理想的。

Use a FileSystemWatcher like below to create a WatcherCreated Event().使用如下所示的FileSystemWatcher创建 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.我用它来创建一个 Windows 服务,该服务监视网络文件夹,然后在新文件到达时通过电子邮件发送给指定的组。

    // 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
    }

FileSystemWatcher is the right answer except that it used to be that FileSystemWatcher only worked for a 'few' changes at a time. FileSystemWatcher 是正确的答案,除了它曾经是 FileSystemWatcher 一次仅适用于“少数”更改。 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.相反,Microsoft 提供了其他工具(编辑:如变更日志)来真正捕获所有变更。 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.一个简单的测试是生成大量的小文件,看看它们是否都被 FileSystemWatcher 报告了。 If you have a problem, I suggest to sidestep the whole issue and scan the file system for changes at a timed interval.如果您遇到问题,我建议您回避整个问题并定期扫描文件系统以查找更改。

如果你想要一些非编程的尝试GiPo@FileUtilities ......但在这种情况下,问题不属于这里!

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.我实现了ReadDirectoryChangesW来监视目录及其所有子目录并获取有关这些目录中更改的信息。

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 . Win32 File Watcher Api 监视目录更改

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:我拿了 Refracted Paladin 的帖子和他分享的FileSystemWatcher并编写了一个快速而肮脏的 C# 实现:

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).要使用它,请下载 Visual Studio(Express 可以)。 The create a new C# console application called Folderwatch and copy and paste my code into your Program.cs.创建一个名为 Folderwatch 的新 C# 控制台应用程序,并将我的代码复制并粘贴到您的 Program.cs 中。

As an alternative you could use Sys Internals Process Monitor: Process Monitor It can monitor the file system and a bunch more.作为替代方案,您可以使用 Sys Internals Process Monitor: Process Monitor它可以监控文件系统等等。

There is no utility or program the comes with Windows to do it.没有 Windows 附带的实用程序或程序可以做到这一点。 Some programming required.需要一些编程。

As noted in another answer, .NET's FileSystemWatcher is the easiest approach.正如另一个答案中所述,.NET 的FileSystemWatcher是最简单的方法。

The native API ReadDirectoryChangesW is rather harder to use (requires an understanding of completion ports).原生 API ReadDirectoryChangesW更难使用(需要了解完成端口)。

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):按照此处的指示在 github 上搜索了几个小时,寻找FileSystemWatcher代码后,我发现以下页面有几个但相似的替代方案,可以解决FileSystemWatcher的缺点(在一些答案中也提到了):

https://github.com/theXappy/FileSystemWatcherAlts 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 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:如果您的项目已经在使用FileSytemWatcher您可以简单地更改它:

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:\");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM