使用FileSystemWatcher监视多个文件夹

33

如何在C#中使用FileSystemWatcher监视多个文件夹(而不是子目录)的最佳方法?

7个回答

24

我认为 FSW 不支持监视多个文件夹,所以您需要为要监视的每个文件夹实例化一个。尽管如此,您可以将事件处理程序指向相同的方法,这样应该能够按照您想要的方式工作。


14

最简单的方法是创建多个 FileSystemWatcher 对象实例。

http://www.c-sharpcorner.com/UploadFile/mokhtarb2005/FSWatcherMB12052005063103AM/FSWatcherMB.aspx

您必须确保正确处理两个文件夹之间的事件:

尽管一些常见事件,如复制或移动文件等,并不直接对应于一个事件,但这些事件会导致事件被触发。当您复制文件时,在复制到的目录中系统会引发一个 "Created" 事件,但在原始目录中不会引发任何事件。当您移动文件时,服务器会引发两个事件:源目录中的 "Deleted" 事件,随后是目标目录中的 "Created" 事件。

例如,您创建了两个 FileSystemWatcher 实例。 FileSystemWatcher1 设置为监视 "C:\My Documents",而 FileSystemWatcher2 设置为监视 "C:\Your Documents"。现在,如果您将一个文件从 "My Documents" 复制到 "Your Documents",FileSystemWatcher2 将引发一个 "Created" 事件,但 FileSystemWatcher1 不会有任何事件被引发。与复制不同,移动文件或目录将引发两个事件。从之前的例子中可以看出,如果您将一个文件从 "My Documents" 移动到 "Your Documents",FileSystemWatcher2 将引发一个 "Created" 事件,并且 FileSystemWatcher1 将引发一个 "Deleted" 事件。

链接到 FileSystemEventArgs


那么我可以使用相同的方法来处理两个目录吗?例如:fileWatcher[index].Created += new FileSystemEventHandler(OnCreated);在上述情况下,OnCreated() 如何知道索引值(或需要监视的目录)呢?谢谢。 - Bi.
@Bi 如果我理解你的问题(今天很长),那么导演信息将作为FileSystemEventArgs参数的一部分传递到OnCreated函数中。 http://msdn.microsoft.com/en-us/library/system.io.filesystemeventargs.aspx - kemiller2002

6

FileSystemWatcher默认只支持监视单个父目录。如果要监视多个兄弟目录,则需要创建多个FileSystemWatcher实例。

但是,您可以通过利用FileSystemWatcher包括子目录的能力来尝试欺骗这种行为。您可以从您正在监视的目录中创建一个NTFS连接点(也称符号链接)作为子目录。Sysinternals的Mark Russinovich有一个名为Junction的实用程序,可简化符号链接的创建和管理。

请注意,您只能创建指向本地计算机上的目录的符号链接。


5

尽管这是一个老问题,但我决定回答它,因为我找不到一个好的答案。因此,目标是使用FileSystemWatcher监视多个文件夹(而不是子目录)?这是我的建议:

using System;
using System.IO;
using System.Security.Permissions;
using System.Collections.Generic;

namespace MultiWatcher
// ConsoleApplication, which monitors TXT-files in multiple folders. 
// Inspired by:
// http://msdn.microsoft.com/en-us/library/system.io.filesystemeventargs(v=vs.100).aspx

{
    public class Watchers
    {
        public static void Main()
        {
            Run();

        }

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public static void Run()
        {
            string[] args = System.Environment.GetCommandLineArgs();

            // If a directory is not specified, exit program.
            if (args.Length < 2)
            {
                // Display the proper way to call the program.
                Console.WriteLine("Usage: Watcher.exe PATH [...] [PATH]";
                return;
            }
            List<string> list = new List<string>();
            for (int i = 1; i < args.Length; i++)
            {
                list.Add(args[i]);
            }
            foreach (string my_path in list)
            {
                Watch(my_path);
            }

            // Wait for the user to quit the program.
            Console.WriteLine("Press \'q\' to quit the sample.");
            while (Console.Read() != 'q') ;
        }
        private static void Watch(string watch_folder)
        {
            // Create a new FileSystemWatcher and set its properties.
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = watch_folder;
            /* Watch for changes in LastAccess and LastWrite times, and
               the renaming of files or directories. */
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
               | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            // Only watch text files.
            watcher.Filter = "*.txt";

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

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

4
FileWatcher 实现了 IDisposable 接口。如果程序退出前不再需要监视器(例如,某个被监视的目录已被删除),建议您包含一种确保调用 IDisposable.Dispose() 方法的模式。 - Eric J.

3

您需要实例化多个FileSystemWatcher对象。虽然您可以将事件绑定到同一方法,并使用发送器对象确定哪个FileSystemWatcher触发了事件。

        var fsw1 = new FileSystemWatcher();
        var fsw2 = new FileSystemWatcher();
        FileSystemEventHandler fsw_changed = delegate(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("{0} - {1}", (sender as FileSystemWatcher).Path, e.ChangeType);
        };
        fsw1.Changed += fsw_changed;
        fsw2.Changed += fsw_changed;

3
您是否可以简单地使用多个FileSystemWatcher实例,每个目录一个实例?

0

或者您可以在代码中传递路径,以标记观察的域的某个范围,就像这样:

{{link1:多监视器链接}}

希望这可以帮助到您。


你指向的链接为每个路径创建一个新的fsw对象。这不是op所要求的。 - Schrodo_Baggins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接